加载DataTable时使用默认列值以避免Null

时间:2013-07-10 20:11:36

标签: sql-server vb.net datatable xsd

我有一个xsd DataSet Schema,它允许我定义DataTable的结构。对于每一列,我都设置了一个默认值,因此在构造新行时,我得到实例化的值(字符串为“”,Ints为0)而不是DbNull

我想在以下两个方法调用之一中使用DataTable.LoadSqlDataAdapter.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时,有没有办法保留每行的默认值?

2 个答案:

答案 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