首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用SqlBulkCopy时没有强制执行约束(一致)

问在使用SqlBulkCopy时没有强制执行约束(一致)
EN

Stack Overflow用户
提问于 2014-02-06 20:19:41
回答 1查看 860关注 0票数 2

在我们的数据库表上,我们使用两个唯一的非聚集索引来创建四个字段的唯一约束。由于其中一个字段的存在,我们使用了两个字段,ZipCode是一个可空字段。如果表中存在一个带有null条目的ZipCode记录,那么我们不希望一个新记录与其他三个字段匹配,但是有一个已定义的ZipCode并被添加(反之亦然)。

问题是,使用SqlBulkCopy似乎没有执行任何约束,因为您可以添加任何您喜欢的记录,而不管表上已经有什么记录。

在另一个程序中,我们使用Entity Framework,因为我们加载的数据量要小得多。使用EF,这些约束非常有效(它们目前正在生产中)。但是,使用SqlBulkCopy,它们似乎被完全忽略了。

T-SQL

代码语言:javascript
复制
CREATE UNIQUE NONCLUSTERED INDEX [UQ_ChannelStateEndDateZipCodeNOTNULL] ON [dbo].[ZipCodeTerritory]
(
    [ChannelCode] ASC,
    [StateCode] ASC,
    [ZipCode] ASC,
    [EndDate] ASC
)
WHERE ([ZipCode] IS NOT NULL)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO
CREATE UNIQUE NONCLUSTERED INDEX [UQ_ChannelStateEndDateZipCodeISNULL] ON [dbo].[ZipCodeTerritory]
(
    [ChannelCode] ASC,
    [StateCode] ASC,
    [ZipCode] ASC,
    [EndDate] ASC
)
WHERE ([ZipCode] IS NULL)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO

C#

代码语言:javascript
复制
Dictionary<DataRow, string> faultyRows = new Dictionary<DataRow, string>();
using (SqlConnection connection = new SqlConnection(connString))
{
    //Open Database connection
    connection.Open();

    //Create transaction objects
    SqlTransaction transaction = connection.BeginTransaction();
    SqlBulkCopy bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.CheckConstraints, transaction);
    bulkCopy.DestinationTableName = "ZipCodeTerritory";

    //Load data and initialize datatable
    DataTable dataTable = LoadData(inserts);
    IDataReader reader = dataTable.CreateDataReader();
    DataTable dataSchema = reader.GetSchemaTable();
    DataTable tmpDataTable = InitializeStructure();

    //Create array to hold data being transfered into tmpDataTable
    object[] values = new object[reader.FieldCount];

    while (reader.Read())
    {
        //Clear temp table for single-record use
        tmpDataTable.Rows.Clear();

        //Get data for current row
        reader.GetValues(values);

        //Load values into the temp table
        tmpDataTable.LoadDataRow(values, true);

        //Load one record at a time
        try
        {
            bulkCopy.WriteToServer(tmpDataTable);
            transaction.Commit();
        }
        catch (Exception ex)
        {
            faultyRows.Add(tmpDataTable.Rows[0], ex.Message);
        }
    }
}

编辑

我发现,如果定义了ZipCode字段,则实际上正在强制执行此约束。ChannelCode、StateCode、ZipCode、EndDate字段的任何匹配都将生成具有以下Message属性的SqlException (从我刚才运行的特定文本中提取):

Cannot insert duplicate key row in object 'dbo.ZipCodeTerritory' with unique index 'UQ_ChannelStateEndDateZipCodeNOTNULL'. The duplicate key value is (9, WA , 98102 , 9999-12-31)

然而,这是唯一一次我可以得到我们的两个限制之一的火。

EN

回答 1

Stack Overflow用户

发布于 2014-02-06 22:16:28

之所以出现这种情况,是因为我使用了将数据从模型对象(我仍在使用实体框架的位置)传输到DataRow的方法。下面是我现在使用的方法。在我修复之前,ZipCode字段(当null )被作为空字符串放置到DataRow列中。因为这在技术上不是空字段,所以没有触发约束。

代码语言:javascript
复制
    private static DataTable LoadData(List<ZipCodeTerritory>zipCodeList, bool update = false)
    {
        DataTable dataTable = InitializeStructure();

        foreach (var zipcode in zipCodeList)
        {
            DataRow row = dataTable.NewRow();

            try
            {
                row[0] = zipcode.ChannelCode.Trim();
                row[1] = zipcode.DrmTerrDesc.Trim();
                row[2] = zipcode.IndDistrnId.Trim();
                row[3] = zipcode.StateCode.Trim();
                row[4] = (string.IsNullOrWhiteSpace(zipcode.ZipCode) ? null : zipcode.ZipCode.Trim());
                row[5] = zipcode.EndDate.Date;
                row[6] = zipcode.EffectiveDate.Date;
                row[7] = zipcode.LastUpdateId;
                row[8] = DateTime.Now.Date;
                row[10] = zipcode.ErrorCodes;
                row[11] = zipcode.Status;

                //Add the Id column if we're doing an update
                if(update) row[9] = zipcode.Id;
            }
            catch (Exception ex)
            {

            }

            dataTable.Rows.Add(row);
        }

        return dataTable;
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21613191

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档