1

我有一个 xsd 数据集架构,它允许我为DataTable. 对于每一列,我都设置了一个默认值,因此在构造新行时,我得到实例化值(“”代表字符串,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.

填充数据表时,有没有办法保留每行的默认值?

4

2 回答 2

0

我也遇到了这个问题。不幸的是,DataTable.Load 或 SqlDataAdapter.Fill 绕过了 xsd 数据集架构中所需的默认值。加载或填充后需要使用代码填写默认值。

使用加载或填充时,您实际上并没有创建新行本身;您正在从其他地方获取行。即使 SQL 实际上是动态创建行也是如此。

比事后使用代码修复数据表更好的解决方案是将填充或加载中的 SQL 更改为使用 IsNull(x, 0) 或 IsNull(x, '')。

于 2013-07-11T05:50:24.323 回答
0

这并没有专门使用加载或填充,但您可以通过读取数据读取器并仅在传入值不为空时设置值来轻松完成此操作。通过SchemaTable从 中获取SqlDataReader,您仍然可以保持加载或填充命令的简单性,而不必写出每个列名。通过添加一个名为 Load 的扩展方法,该方法采用默认行参数,您可以在自己实现功能的同时保留 Load 函数的外观

使用默认行参数加载扩展方法:

''' <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
于 2013-07-11T14:39:28.100 回答