我正在将数据从表A复制到表B. 表B有一个可为空的列,其默认约束值为0。 通常,我使用以下访问器设置列的值。
public object this[string columnName]
{
get { return DataTable.Rows[CurrentRow][columnName]; }
set { DataTable.Rows[CurrentRow][columnName] = value; }
}
但我不设置我的可空列X.
插入整行时,不使用默认值。而不是0,为可为空的列插入了NULL。
_sqlCommandBuilder = new SqlCommandBuilder(_sqlDataAdapter);
_sqlCommandBuilder.ConflictOption = ConflictOption.OverwriteChanges;
_sqlCommandBuilder.SetAllValues = false;
_sqlDataAdapter.Update(DataTable);
我也得到了架构:
_sqlDataAdapter.Fill(DataTable);
_sqlDataAdapter.FillSchema(_dataTable, SchemaType.Mapped);
为什么我的列X的ADO.NET设置为NULL虽然我没有设置它?
我认为当我没有设置X列的值时,ADO.NET会从给定的约束中获取默认值。
ADO.NET CommandBuilder是否能够使用默认约束?
答案 0 :(得分:3)
您无需使用CommandBuilder
来实施DataAdapter
的更新方法。 CommandBuilder
充满了问题。您可以将DataAdapter.SelectCommand
和DataAdapter.UpdateCommand
属性设置为直接指定sql的DbCommand
对象。这避免了CommandBuilder
生成正确的sql语句的能力所固有的问题。
更新
CommandBuilder无法知道您要使用默认值。它只是生成一个insert语句,如果有一个列,它将为insert语句生成它。如果该列是insert语句的一部分,那么将插入为该列指定的任何值,即使为null。默认值适用于未在insert语句中包含它的情况。无论您如何尝试插入项目,也不会将null转换为默认值。
继续沿着这条试图使用CommandBuilder的道路只会让你更加悲伤。它甚至无法在select子句中处理简单的连接语句。它还需要一个主键。如果违反其中任何一个,则无法生成正确的更新,插入和删除语句。只有两个提供程序,Sql Server和Oracle,已经实现了这个类,并且已知Oracle有一些从未在上述基本问题之外修复的错误。
如果您使用了两个DbCommand对象,一个用于选择,一个用于插入,然后通过DbDataReader循环选择DbCommand的输出,您可以轻松地检查该列中的null并为其提供默认值零插入DbCommand,因为你知道它是什么。了解数据库的规则并在必要时使用它们并不违反任何类型的代码组织规则。无论如何,你必须知道数据库中的内容才能编写这种代码。
如果您有sql server 2005或更高版本,另一个建议是使用INSERT INTO .. SELECT语句。如果你的sql足够好,你可以使用CASE子句来创建一个sql语句。
答案 1 :(得分:0)
一个小问题,似乎很明显,但事实上它很棘手。
_sqlCommandBuilder.ConflictOption = ConflictOption.OverwriteChanges;
如果我引用MSDN definition,您可以阅读:
"If no PrimaryKey is defined, all searchable columns are included in the WHERE clause."
我的一个朋友,用于在某些镜头中定义IDENTITY(1,1)而不是主键。
这么小的问题是,你在“更新的”表格中使用主键B ??
然后....
要添加信息,SqlAdapter.FillSchema不使用默认值 以下是FillSchema检索的信息:
AllowDBNull
AutoIncrement.You must set AutoIncrementStep and AutoIncrementSeed separately.
MaxLength
ReadOnly
Unique
(引自MSDN site)
独特