当前位置:编程学习 > C#/ASP.NET >>

用VB.NET不能更新ACCESS的字段,请帮忙诊断一下,谢谢。

本人用以下代码能够顺利的从DataGridView中查询到ACCESS的数据(其中的"时间"字段经过处理)
Schedule_Ada.SelectCommand = New OleDbCommand("SELECT 流水号,日期,(Hour(时间) & ':' & Minute(时间)) as 时间 from Schedule", Schedule_Cnn)
Schedule_Ada.Fill(MyDS, "Schedule")
但是我想把改动后的结果更新数据源的话,"时间"字段却怎么都更新不了(流水号,日期这些没有处理过的字段倒是可以更新)
Schedule_Ada.Update(MyDS, "schedule")
MyDS.AcceptChanges()
找了很久也没找到解决办法,请高人指点。


--------------------编程问答-------------------- Access 中的日期字段是 "#2012-03-08#" 这样的。 --------------------编程问答-------------------- 我是菜鸟,应该是你的DATATABLE中的字段名和数据源中的字段名不统一导致. --------------------编程问答-------------------- 是这样的,在ACCESS里面的“时间”字段里面,我输入的内容是“08:30”,如果按照以下代码读取的话,时间字段就会编程“1899-12-30 08:30”,
Schedule_Ada.SelectCommand = New OleDbCommand("SELECT 流水号,日期,时间 from Schedule", Schedule_Cnn)
所以我才用以下代码进行处理,处理后,“时间”字段的名称变成了“expr1002”
Schedule_Ada.SelectCommand = New OleDbCommand("SELECT 流水号,日期,(Hour(时间) & ':' & Minute(时间)) as 时间 from Schedule", Schedule_Cnn)
我也考虑过字段名称不同,所以我用下面的代码将字段"expr1002"改成了时间,但还是不行。
MyDS.Tables("Schedule").Columns("Expr1002").ColumnName = "时间"
我还考虑过用以下代码也不行
Schedule_DTM = Schedule_Ada.TableMappings.Add("Schedule", "Schedule")
Schedule_DTM.ColumnMappings.Add("Expr1002", "时间")


以上是我这种菜鸟的各种尝试都未能成功,我就用我自己的话来概括一下这个问题
    如何用Datatable中指定的列更新数据源中指定的列 --------------------编程问答-------------------- 你要重写你的更新命令,指定Schedule_Ada 的InsertCommand 和 UpdateCommand
--------------------编程问答-------------------- 这个我也想到了,暂且不管InsertCommand命令,我尝试修改UpDateCommand命令,但是不管怎么写代码都搞不定,楼上的能指点一下该怎么写么?我用了?,也尝试用列的名称,但都不行啊。 --------------------编程问答-------------------- 大致是这样,
dim cmd as new oledbCommand("update Schedule set 流水号=@流水号,日期=@日期 where...",Schedule_Cnn)
cmd.Parameters.Add("@流水号", OleDb.OleDbType.Integer, 4, "流水号")
cmd.Parameters.Add("@日期", OleDb.OleDbType.DBDate, 4, "日期")
这样第三列就不会出现在UpdateCommand中
Schedule_Ada.UpdateCommand=cmd
其它的楼主自己看看MSDN --------------------编程问答-------------------- cmd.Parameters.Add("@日期", OleDb.OleDbType.DBDate, 4, "日期")
4表示数据的存储长度,不同的数据类型不同,好象全用0都行 --------------------编程问答-------------------- 楼上说的我有时间去试试看看。多谢各位了。 --------------------编程问答-------------------- 跟朋友们汇报一下我的测试结果,我将ACCESS数据库的表"Schedule"的结构改成简单的两个字段"时间"和"项目",“时间”字段为关键字字段

我用以下代码,假设某条记录的"时间"字段在ACCESS里面显示的是"09:30",我如果用直接用以下代码就在VB.NET中显示的是"1899-12-31 09:30"
Schedule_Ada.SelectCommand = New OleDbCommand("SELECT 时间,项目 FROM Schedule", Schedule_Cnn)

所以我把代码改成下面的,ACCESS里面的"时间"字段在VB.NET里面就是显示的是"09:30"了,但是显示的字段名变成了"Expr1000"
Schedule_Ada.SelectCommand = New OleDbCommand("SELECT Hour(时间) & ':' & Minute(时间),项目 FROM Schedule", Schedule_Cnn)

然后我没有使用OleDbCommandBuilder来生成默认的SQL语句,而是使用“lhblxm”朋友提到的语句,我是这么写的:
Dim MyCmd = New OleDbCommand("update schedule set 项目=@项目,时间=@Expr1000", Schedule_Cnn)
MyCmd.Parameters.Add("@项目", OleDbType.BSTR, 8, "项目")
MyCmd.Parameters.Add("@时间", OleDbType.Date, 4, "Expr1000")
Schedule_Ada.UpdateCommand = MyCmd
Schedule_Ada.Update(MyDS, "schedule")
MyDS.AcceptChanges()

根据测试,能够将DataTable中的"Expr1000"中修改的内容更新到ACCESS的"Schedule"表的"时间"
字段了,但是会在 MyDS.AcceptChanges()这个地方有如下错误提示,
“由于将在索引、 主关键字、或关系中创建重复的值,请求对表的改变没有成功。 改变该字段中的或包含重复数据的字段中的数据,删除索引或重新定义索引以允许重复的值并再试一次”

因为修改成功了,但是有上面的错误提示的话,我猜想是不是表示做了两次更新呢?麻烦各位了。 --------------------编程问答-------------------- 如果是UPDATE 语句,没加WHERE条件,则更新整个表,
如果字段是表的主键,则更新会失败 --------------------编程问答-------------------- 根本就不是这个问题,是因为“时间”字段是你自己额外附加出来的,Schedule压根没这个字段,所以DataGridView的这列在数据库这张表中实际是没有对应的字段的,你用DataGridView去更新当然更新失败。
像这样你自加了字段出来的,更新要使用sql语句来操作,日期这个字段你要用拼接,也就是你DataGridView中的日期列+时间列才对应了你这张表中的日期字段。 --------------------编程问答-------------------- 是啊,为了显示,你是通过重新组织数据库里的字段来实现显示的。这样不能直接更新的。你要朕对你的现实规则反过来将要更新的数据重新组织为你数据库里字段允许的值。 --------------------编程问答--------------------
引用 10 楼 lhblxm 的回复:
如果是UPDATE 语句,没加WHERE条件,则更新整个表,
如果字段是表的主键,则更新会失败


    是啊,可是要怎么写条件语句才能让UPDATE只对变动的记录,而不是所有的记录进行更新呢?这个问题看MSDN看的我头都大了。 --------------------编程问答-------------------- 是用游标?还是用OUTPUT呢?还是其他呢 --------------------编程问答-------------------- 你的表的设计中是否有一个字段是“自动编号”类型的,如果有,可以设置它为主鍵,
除非你有特别的要求,一般都是如此,而且用起来会很方便。
看来楼主的“流水号”应该是的

dim cmd as new oledbCommand("update Schedule set 日期=@日期 where 流水号=@流水号,",Schedule_Cnn)
--------------------编程问答--------------------
引用 15 楼 lhblxm 的回复:
你的表的设计中是否有一个字段是“自动编号”类型的,如果有,可以设置它为主鍵,
除非你有特别的要求,一般都是如此,而且用起来会很方便。
看来楼主的“流水号”应该是的

dim cmd as new oledbCommand("update Schedule set 日期=@日期 where 流水号=@流水号,",Schedule_Cnn)


楼上说的没错,我刚才单独加一个关键字段“流水号”(此关键字段不用于修改的情况下),是能够达到我的要求了,不过我今天早上测试的是将“时间”作为关键字段(因为想着反正这个字段也不能重复,干脆做关键字段来简化ACCESS表的结构),我将变更后的"时间"字段更新回ACCESS表就一直搞不定,所以:
如何才能更新ACCESS的关键字段呢? --------------------编程问答-------------------- 我尝试着将ACCESS表修改成只有"时间"一个字段且是关键字段,然后

Schedule_Ada.SelectCommand = New OleDbCommand("SELECT Hour(时间) & ':' & Minute(时间) FROM Schedule", Schedule_Cnn)

Dim MyCmd = New OleDbCommand("update schedule set 时间=@Expr1000 Where 时间=@Expr1000", Schedule_Cnn)

MyCmd.Parameters.Add("@时间", OleDbType.Date, 4, "Expr1000")

Schedule_Ada.UpdateCommand = MyCmd

Schedule_Ada.Update(MyDS, "schedule")

MyDS.AcceptChanges()

结果是错误提示:
"违反并发性: UpdateCommand 影响了预期 1 条记录中的 0 条。" --------------------编程问答--------------------
引用 17 楼 followsense 的回复:
我尝试着将ACCESS表修改成只有"时间"一个字段且是关键字段,然后

Schedule_Ada.SelectCommand = New OleDbCommand("SELECT Hour(时间) & ':' & Minute(时间) FROM Schedule", Schedule_Cnn)

Dim MyCmd = New OleDbCommand("update sc……

我说的很清楚了,你这个时间字段是你自己用“Hour(时间)” + “ Minute(时间)”这样拼接起来的,而不是你表中就有的字段,你表中的字段只有“时间”!你这样的语句其实就是一个视图语句而你,视图是不可以update的!!!你这样改只能改动内存中的临时表,从临时表到数据库中对应字段是无法被改动的! --------------------编程问答--------------------
引用 18 楼 ziyouli 的回复:
引用 17 楼 followsense 的回复:
我尝试着将ACCESS表修改成只有"时间"一个字段且是关键字段,然后

Schedule_Ada.SelectCommand = New OleDbCommand("SELECT Hour(时间) & ':' & Minute(时间) FROM Schedule", Schedule_Cnn)

Dim ……



为了简单起见,我将ACCESS表修改为只有一个字段"流水号"且是关键字段,字段类型是整数型,只有2条记录,分别为"流水号"=1和"流水号"=2,用以下代码获取ACCESS表Schedul内容到DataTable,未对字段做任何修改
Schedule_Ada.SelectCommand = New OleDbCommand("SELECT 流水号 FROM Schedule", Schedule_Cnn)
Schedule_Ada.Fill(MyDS, "Schedule")
Dim MyCmd = New OleDbCommand("update schedule set 流水号=@流水号 Where 流水号=@流水号", Schedule_Cnn)
DataGridView1.DataSource = MyDS.Tables("Schedule")

然后我在DataGridView1里面将记录"流水号"=1修改为"流水号"=10

然后我用下面代码更新ACCESS数据库
Dim MyCmd = New OleDbCommand("update schedule set 流水号=@流水号 Where 流水号=@流水号", Schedule_Cnn)
MyCmd.Parameters.Add("@流水号", OleDbType.BigInt, 4, "流水号")
Schedule_Ada.UpdateCommand = MyCmd
Schedule_Ada.Update(MyDS, "schedule")
MyDS.AcceptChanges()

就会出现如下错误:
"违反并发性: UpdateCommand 影响了预期 1 条记录中的 0 条。"

所以我的意思是说,在这种情况下对关键字段的改动的更新如何写代码呢?

--------------------编程问答-------------------- 上面的内容要修改一下,如下:



引用 18 楼 ziyouli 的回复:
引用 17 楼 followsense 的回复:
我尝试着将ACCESS表修改成只有"时间"一个字段且是关键字段,然后

Schedule_Ada.SelectCommand = New OleDbCommand("SELECT Hour(时间) & ':' & Minute(时间) FROM Schedule", Schedule_Cnn)

Dim ……



为了简单起见,我将ACCESS表修改为只有一个字段"流水号"且是关键字段,字段类型是整数型,只有2条记录,分别为"流水号"=1和"流水号"=2,用以下代码获取ACCESS表Schedul内容到DataTable,未对字段做任何修改
Schedule_Ada.SelectCommand = New OleDbCommand("SELECT 流水号 FROM Schedule", Schedule_Cnn)
Schedule_Ada.Fill(MyDS, "Schedule")
DataGridView1.DataSource = MyDS.Tables("Schedule")

然后我在DataGridView1里面将记录"流水号"=1修改为"流水号"=10

然后我用下面代码更新ACCESS数据库
Dim MyCmd = New OleDbCommand("update schedule set 流水号=@流水号 Where 流水号=@流水号", Schedule_Cnn)
MyCmd.Parameters.Add("@流水号", OleDbType.BigInt, 4, "流水号")
Schedule_Ada.UpdateCommand = MyCmd
Schedule_Ada.Update(MyDS, "schedule")
MyDS.AcceptChanges()

就会出现如下错误:
"违反并发性: UpdateCommand 影响了预期 1 条记录中的 0 条。"

所以我的意思是说,在这种情况下对关键字段的改动的更新如何写代码呢? --------------------编程问答-------------------- 既然@表示修改后的变量,那怎么样将修改前的数据也作为一个变量呢 --------------------编程问答--------------------
引用 20 楼 followsense 的回复:
上面的内容要修改一下,如下:




引用 18 楼 ziyouli 的回复:

引用 17 楼 followsense 的回复:
我尝试着将ACCESS表修改成只有"时间"一个字段且是关键字段,然后

Schedule_Ada.SelectCommand = New OleDbCommand("SELECT Hour(时间) & ':' &am……

内置的update不能对主键进行更新,你把主键修改了,他提交你修改请求的时候找不到原始主键值了。 --------------------编程问答-------------------- 这种常用的东西还是自己吧ACCESS各项操作写个class方便;
下面是一个update的,单个更新;
    Public Shared Sub UpDateRecords1(ByVal ConnectionStr As String, ByVal AccesTableName As String, _
ByVal Cols() As String, ByVal Vals() As Object, ByVal IndexColumnName As String, ByVal IndexValue As Object, ByVal isShows_qlString As Boolean)
        Dim myConn As New OleDb.OleDbConnection(ConnectionStr)
        Using myConn
            myConn.Open()
            Dim sqlString As String = ""
            sqlString = "update " & AccesTableName & " set "
            Dim i As Integer
            If Cols.Length > 1 Then
                For i = 0 To Cols.Length - 2
                    sqlString = sqlString & Cols(i) & "=" & Vals(i) & ", "
                Next
                sqlString = sqlString & Cols(Cols.Length - 1) & "=" & Vals(Cols.Length - 1) & " where " & IndexColumnName & "=" & IndexValue
            Else
                sqlString = sqlString & Cols(0) & "=" & Vals(0) & " where " & IndexColumnName & "=" & IndexValue
            End If
            If isShows_qlString = True Then MsgBox(sqlString, MsgBoxStyle.Information, "查询语句如下:")
            Dim cmd As OleDbCommand = New OleDbCommand(sqlString, myConn)
            For i = 0 To Cols.Length - 1
                If Vals(i) IsNot Nothing Then
                    cmd.Parameters.Add(New OleDb.OleDbParameter).Value = Vals(i)
                Else
                    cmd.Parameters.Add(New OleDb.OleDbParameter).Value = DBNull.Value
                End If
            Next
            cmd.ExecuteNonQuery()
        End Using
    End Sub --------------------编程问答-------------------- #Region "保存到数据库"
    Public Shared Sub SaveAllRecords(ByVal ConnectionString As String, ByVal sourceTableName As String, ByVal objDataTable As DataTable)
        Dim sqlString As String = " SELECT * FROM " & sourceTableName
        Dim da As OleDbDataAdapter = New OleDbDataAdapter(sqlString, ConnectionString)
        Dim comBuilder As New OleDbCommandBuilder(da)
        da.Update(objDataTable)
    End Sub
#End Region --------------------编程问答--------------------
引用 22 楼 ziyouli 的回复:
引用 20 楼 followsense 的回复:
上面的内容要修改一下,如下:




引用 18 楼 ziyouli 的回复:

引用 17 楼 followsense 的回复:
我尝试着将ACCESS表修改成只有"时间"一个字段且是关键字段,然后

Schedule_Ada.SelectCommand = New OleDbCommand("SELECT Hour(时间……


你虽然说的有道理,但是为什么用OldCommandBuilder自动生成的Update,Insert和Delete语句,同样是Schedule表里面只有一个字段"流水号"其是关键字段的情况下,我能很好的更新,而我不用OldCommandBuilder自动生成,自己写的Update语句就不行呢?
Private Schedule_CoB As New OleDbCommandBuilder
Schedule_CoB = New OleDbCommandBuilder(Schedule_Ada)
Schedule_Ada.Fill(MyDS, "Schedule")
Schedule_Ada.SelectCommand = New OleDbCommand("SELECT 流水号 FROM Schedule", Schedule_Cnn)
Schedule_CoB = New OleDbCommandBuilder(Schedule_Ada)
Schedule_Ada.Fill(MyDS, "Schedule")


OldCommandBuilder自动生成的Update,Insert和Delete语句是什么样的呢?我照着写不就行了么? --------------------编程问答-------------------- 以下是这个朋友说的ziyouli

内置的update不能对主键进行更新,你把主键修改了,他提交你修改请求的时候找不到原始主键值了。

他虽然说的有道理,但是为什么用OldCommandBuilder自动生成的Update,Insert和Delete语句,同样是Schedule表里面只有一个字段"流水号"其是关键字段的情况下,我能很好的更新,而我不用OldCommandBuilder自动生成,自己写的Update语句就不行呢?
Private Schedule_CoB As New OleDbCommandBuilder
Schedule_CoB = New OleDbCommandBuilder(Schedule_Ada)
Schedule_Ada.Fill(MyDS, "Schedule")
Schedule_Ada.SelectCommand = New OleDbCommand("SELECT 流水号 FROM Schedule", Schedule_Cnn)
Schedule_CoB = New OleDbCommandBuilder(Schedule_Ada)
Schedule_Ada.Fill(MyDS, "Schedule")

OldCommandBuilder自动生成的Update,Insert和Delete语句是什么样的呢?我照着写不就行了么? --------------------编程问答-------------------- new OleDbParameter("@Title", OleDbType.LongVarWChar, 255, "MyTitle");
要加 OleDbType.LongVarWChar, 255这些信息,参见
http://dotnet.aspx.cc/file/Insert-DataSet-Into-Access.aspx --------------------编程问答-------------------- 照着写在数据及设计器里是可以的,我曾经这样做过,当时是拖拽过数据表之后,有的只给出了SelectCommand,所以我就自己补充了其他语句,但里面的参数的照着SelectCommand的参数写,不然无法识别。就像你说的那样。 --------------------编程问答-------------------- 对于你的问题,你想使用Adapter吗?首先你的Select语句就不应该改动数据库字段,否则怎么可能更新回去?你可以通过格式化输出样式的方式解决。
补充:.NET技术 ,  VB.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,