Пример SqlBulkCopy WriteToServer. Что я делаю неправильно? - PullRequest
0 голосов
/ 10 февраля 2010

Это может быть долго, но я хочу объяснить мой пример

Я получил этот код:

#region [parent table]
DataTable dtParent = new DataTable();
DataColumn dc;

dc = new DataColumn();
dc.DataType = System.Type.GetType("System.Int32");
dc.ColumnName = "Id";
dc.Unique = true;
dc.AutoIncrement = true;
dtParent.Columns.Add(dc);

dc = new DataColumn();
dc.DataType = System.Type.GetType("System.String");
dc.ColumnName = "Title";
dc.Unique = false;
dtParent.Columns.Add(dc);

dtParent.TableName = "aTestSw";
dtParent.PrimaryKey = new DataColumn[] { dtParent.Columns[0] };
#endregion

#region [child table]
DataTable dtChild = new DataTable();

dc = new DataColumn();
dc.DataType = System.Type.GetType("System.Int32");
dc.ColumnName = "Id";
dc.Unique = true;
dc.AutoIncrement = true;
dtChild.Columns.Add(dc);

dc = new DataColumn();
dc.DataType = System.Type.GetType("System.Int32");
dc.ColumnName = "ParentId";
dc.Unique = false;
dtChild.Columns.Add(dc);

dc = new DataColumn();
dc.DataType = System.Type.GetType("System.String");
dc.ColumnName = "Description";
dc.Unique = false;
dtChild.Columns.Add(dc);

dtChild.TableName = "aTestSwChild";
dtChild.PrimaryKey = new DataColumn[] { dtChild.Columns[0] };
#endregion

DataSet DataSet1 = new DataSet();
DataSet1.Tables.Add(dtParent);
DataSet1.Tables.Add(dtChild);

#region [fk]
DataColumn parentColumn = dtParent.Columns["Id"];
DataColumn childColumn = dtChild.Columns["ParentId"];
DataRelation relParentChild = new DataRelation("ParentChild", 
    parentColumn, childColumn);
DataSet1.Relations.Add(relParentChild); 
#endregion

#region [fill parent]
DataRow dr2saveIn = dtParent.NewRow();
dr2saveIn["Title"] = "a";
dtParent.Rows.Add(dr2saveIn);

dr2saveIn = dtParent.NewRow();
dr2saveIn["Title"] = "b";
dtParent.Rows.Add(dr2saveIn);
#endregion

#region [fill child]
dr2saveIn = dtChild.NewRow();
dr2saveIn["Description"] = "c";
dr2saveIn["ParentId"] = dtParent.Rows[0]["Id"];
dtChild.Rows.Add(dr2saveIn);

dr2saveIn = dtChild.NewRow();
dr2saveIn["Description"] = "d";
dr2saveIn["ParentId"] = dtParent.Rows[1]["Id"];
dtChild.Rows.Add(dr2saveIn);   
#endregion

SqlBulkCopy bulkCopy = new SqlBulkCopy(
    "server=aaa;database=bbb;uid=ccc;password=ddd", 
    SqlBulkCopyOptions.TableLock);
bulkCopy.DestinationTableName = "dbo.aTestSw";
bulkCopy.WriteToServer(dtParent);
bulkCopy.DestinationTableName = "dbo.aTestSwChild";
bulkCopy.WriteToServer(dtChild);

Когда я его запустил, я получил данные, которые "выглядят" правильно в столбце FK дочерней таблицы. (0 и 1) Дело в том, что после сохранения данные попадают в базу данных, но не все в порядке. Вместо того, чтобы иметь идентификатор FK из родительской таблицы, я получил 0 и 1 из кода C #. Примечание: таблицы в БД ДОЛЖНЫ ИМЕТЬ FK. Вы не можете добавить это вручную, но SqlBulkCopy WriteToServer не имеет проблем, в любом случае записывает неверные данные (как будто они не проверяются на ограничения)

Посмотрите таблицы:

CREATE TABLE [dbo].[aTestSw](
 [Id] [int] IDENTITY(1,1) NOT NULL,
 [Title] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
 CONSTRAINT [PK_aTestSw] PRIMARY KEY CLUSTERED 
(
 [Id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]


CREATE TABLE [dbo].[aTestSwChild](
 [Id] [int] IDENTITY(1,1) NOT NULL,
 [ParentId] [int] NOT NULL,
 [Description] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
 CONSTRAINT [PK_aTestSwChild] PRIMARY KEY CLUSTERED 
(
 [Id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[aTestSwChild]  WITH NOCHECK ADD  CONSTRAINT [FK_aTestSwChild_aTestSw] FOREIGN KEY([ParentId])
REFERENCES [dbo].[aTestSw] ([Id])

ALTER TABLE [dbo].[aTestSwChild] CHECK CONSTRAINT [FK_aTestSwChild_aTestSw]

Результаты выглядят так:

select * from aTestSw

Id          Title
16          a
17          b

select * from aTestSwChild

Id          ParentId    Description
12          0           c
13          1           d

Что я делаю не так? Вероятно, я не должен получить Id, как это в C #. Но как? Или это вообще возможно? Я имею в виду, как мой второй bulkinsert узнает SQL !!!! идентификатор на вставке?

Ответы [ 2 ]

1 голос
/ 12 февраля 2010

использование этой опции:

SqlBulkCopyOptions.KeepIdentity

перед действием массового копирования установите CheckConstraints вашей базы данных на OFF. после этого вставьте свои данные, используя массовое копирование. когда вся ваша работа будет выполнена, установите для параметра CheckConstraints значение ON.

опция upside заставляет вашу базу данных сохранять ваши значения идентичности.

0 голосов
/ 28 февраля 2013

По умолчанию SqlBulkCopy превратит ваши внешние ключи в внешние ключи nocheck. Вам нужно добавить опцию SqlBulkCopyOptions.CheckConstraints, чтобы ваши внешние ключи проверяли все существующие и все новые данные.

...