Пример SqlBulkCopy WriteToServer. Что я делаю не так?

c# sql sqlbulkcopy sql-server

Вопрос

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

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

#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 #. Но как? Или это даже возможно? Я имею в виду, как мой второй объемный тест будет знать SQL !!!! id на вставке?

Принятый ответ

использование этого варианта:

SqlBulkCopyOptions.KeepIdentity

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

опцион «вверх» заставляет ваш дБ сохранять ваши идентификационные значения.


Популярные ответы

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



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow