我在oracle db中有一个表HolidayHome,它在Id上有唯一的db索引(我没有在代码中以任何方式为adapter / table / dataset指定这个,不知道我应该/可以)。
DbDataAdapter.SelectCommand是这样的:
SELECT Id, ExtId, Label, Location1, Location2, Location3, Location4, ClassId, X, Y, UseType FROM HolidayHome
但DbCommandBuilder生成的UpdateCommand有很奇怪的where子句:
UPDATE HOLIDAYHOME SET ID = :p1, EXTID = :p2, LABEL = :p3, LOCATION1 = :p4, LOCATION2 = :p5, LOCATION3 = :p6, LOCATION4 = :p7, CLASSID = :p8, X = :p9, Y = :p10, USETYPE = :p11 WHERE ((ID = :p12) AND ((:p13 = 1 AND EXTID IS NULL) OR (EXTID = :p14)) AND ((:p15 = 1 AND LABEL IS NULL) OR (LABEL = :p16)) AND ((:p17 = 1 AND LOCATION1 IS NULL) OR (LOCATION1 = :p18)) AND ((:p19 = 1 AND LOCATION2 IS NULL) OR (LOCATION2 = :p20)) AND ((:p21 = 1 AND LOCATION3 IS NULL) OR (LOCATION3 = :p22)) AND ((:p23 = 1 AND LOCATION4 IS NULL) OR (LOCATION4 = :p24)) AND (CLASSID = :p25) AND (X = :p26) AND (Y = :p27) AND (USETYPE = :p28))
所有这些字段都有:
((:p17 = 1 AND LOCATION1 IS NULL) OR (LOCATION1 = :p18))
在oracle db中定义如下:
LOCATION1 VARCHAR2(30)
所以他们允许空值。
代码如下所示:
static bool CreateInsertUpdateDeleteCmds(DbDataAdapter dataAdapter) { DbCommandBuilder builder = _trgtProvFactory.CreateCommandBuilder(); builder.DataAdapter = dataAdapter; // Get the insert, update and delete commands. dataAdapter.InsertCommand = builder.GetInsertCommand(); dataAdapter.UpdateCommand = builder.GetUpdateCommand(); dataAdapter.DeleteCommand = builder.GetDeleteCommand(); }
该怎么办? UpdateCommand非常疯狂。
谢谢&最诚挚的问候:马蒂
答案 0 :(得分:2)
我真的不知道那些((:px = 1 AND XXX IS NULL)或(XXX =:py))的目的,但是CommandBuilder会生成一个where子句来检查正在更新的行是否已被更新你加载后改了。例如,如果您使用值(c1,c2,c3,...,cn)加载行R1并使用c3'更改c3的值,则更新命令文本具有where子句,该子句检查所有原始值行(例如,C1 = c1和C2 = c2和......)。如果更新命令影响0行,则表示其他人在您加载它的时间与更新它之间的时间内更新了该行,并且它会抛出DbConcurrencyException。我知道你可以改变这种行为(不记得具体如何)。
这就是更新命令中Where子句的主要原因。
答案 1 :(得分:0)
问题与DataTable中数据库NULL的表示方式以及如何测试数据库中列的值是否仍为NULL有关
在SQL中,NULL不是一个值,它是一个状态..所以你不能像这样测试一个sql列为NULL:WHERE MyColumn = NULL
,这个测试总会返回false
因此您需要在WHERE
中进行两项不同的测试,以检查实际的列状态是否仍然相同。
DataRows保留旧值和新值,因此更新命令应为:
UPDATE MyTable
SET KeyColumn = KeyDatacolumn.NewValue, OtherColumn = OtherDataColumn.NewValue
WHERE KeyColumn = KeyDatacolumn.OldValue AND OtherColumn = OtherDataColumn.OldValue
请注意,只需要在OtherColumn上使用WHERE条件,以避免覆盖其他人对同一记录的更新
但是,如前所述,如果OtherColumn可以为空,我们就不能简单地测试WHERE OtherColumn = OtherDataColumn.OldValue
所以更新命令将是:
UPDATE MyTable
SET KeyColumn = KeyDatacolumn.Value, OtherColumn = OtherDataColumn.NewValue
WHERE
(KeyColumn = KeyDatacolumn.OldValue) AND
(
(OtherColumn = OtherDataColumn.OldValue)
OR
(
(OtherDataColumn.OldValue.Equals(DBNull))
AND
(OtherColumn IS NULL)
)
)
你可以读取OtherColumn上的条件,例如"其中OtherColumn具有与OR
之前相同的值(它为NULL AND
它仍为NULL)"
因此,对于可为空的列,每列将使用2个不同的参数,第一个将作为DataColumn.OldValue.Equals(DBNull)
传递,第二个将作为IIF(DataColumn.OldValue.Equals(DBNull), "NULL", DataColumn.OldValue)
传递
我希望得到任何帮助 问候