我有一个xsd DataSet Schema,它允许我定义DataTable
的结构。对于每一列,我都设置了一个默认值,因此在构造新行时,我得到实例化的值(字符串为“”,Ints为0)而不是DbNull
我想在以下两个方法调用之一中使用DataTable.Load
或SqlDataAdapter.Fill
时保留
Dim table1 As New CodeSetSchemas.EntityByRoleDataTable()
Using reader As SqlDataReader = cmd.ExecuteReader()
table1.Load(reader)
End Using
Dim table2 As New CodeSetSchemas.EntityByRoleDataTable()
Using adapter As New SqlDataAdapter(cmd)
adapter.Fill(table2)
End Using
但是当这些方法中的任何一个创建一个新行时,它们实际上会将数据库中的DbNull写入该行。如果我将每列的AllowDBNull
属性设置为False
,则会出现以下异常:
Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.
填充DataTable时,有没有办法保留每行的默认值?
答案 0 :(得分:0)
我也遇到了这个问题。不幸的是,DataTable.Load或SqlDataAdapter.Fill会绕过xsd数据集架构中的所需默认值。您需要使用代码在加载或填充后填写默认值。
使用加载或填充时,您实际上并不是在创建新行;你从其他地方获取行。即使SQL实际上是在动态创建行,也是如此。
比使用代码修复数据表更好的解决方案是在填充或加载中更改SQL以使用IsNull(x,0)或IsNull(x,'')。
答案 1 :(得分:0)
这不是专门使用加载或填充,但是只需读入数据读取器并且仅在传入值不为空时设置值,就可以非常轻松地完成此操作。通过从SqlDataReader
获取SchemaTable
,您仍然可以通过不必写出每个列名来保留加载或填充命令的简单性。通过添加名为Load的Extension方法接受默认行参数,您可以在自己实现功能的同时保留Load函数的外观
使用默认行Arg加载扩展方法:
''' <summary>
''' Fills a <c>System.Data.DataTable</c> with values from a data source using the supplied <c>System.Data.SqlDataReader</c>.<br/>
''' Each row is new row is given the default values from the new row and incoming nulls are ignored
''' </summary>
''' <param name="dt">DataTable to fill</param>
''' <param name="reader">A <c>System.Data.SqlDataReader</c> that provides a result set.</param>
''' <param name="defaultRow">Default values for each DataRow</param>
''' <remarks></remarks>
<Extension()> _
Public Sub Load(ByVal dt As DataTable, ByVal reader As SqlDataReader, ByVal defaultRow As DataRow)
Dim newRow As DataRow
'get incoming data fields
Dim columns As List(Of String)
columns = reader.GetSchemaTable.AsEnumerable _
.Select(Function(r) CStr(r("ColumnName"))).ToList()
While reader.Read()
'make new row and set default item array
newRow = dt.NewRow()
newRow.ItemArray = defaultRow.ItemArray
'copy over new values
For Each col As String In columns
If Not IsDBNull(reader(col)) Then newRow(col) = reader(col)
Next
dt.Rows.Add(newRow)
End While
End Sub
调用您的加载方法,如下所示:
Dim roleTable As New CodeSetSchemas.EntityByRoleDataTable()
Using reader As SqlDataReader = cmd.ExecuteReader()
roleTable.Load(reader, roleTable.NewEntityByRoleRow())
End Using