2

我试图从一个文本文件中获取数千张发票(和其他东西)并将它们插入 SQL Server 2008。我编写了一个小控制台应用程序来执行此操作,它使用 LINQ to SQL。插入所有现有发票后,我希望将Invoice_ID其作为标识列并自动递增,因此我将其设计为:

CREATE TABLE [dbo].[Invoice]
(
 [Invoice_ID] int IDENTITY(1,1) NOT NULL PRIMARY KEY, 
    /* Other fields elided */
)

在我开始插入发票之前,我调用了一个包含以下行的存储过程:

SET IDENTITY_INSERT [dbo].[Invoice] ON;
/* Other lines for setup elided */

提交更改后,我使用以下行调用另一个存储过程:

SET IDENTITY_INSERT [dbo].[Invoice] OFF;
/* Other lines for clean up elided */

当我尝试插入发票并提交更改时,出现以下异常:

SQLException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“发票”中插入标识列的显式值。

我运行了 SQL Profiler,我可以看到它在尝试执行插入之前确实设置IDENTITY_INSERT为。ON我没有看到它被设置到OFF任何地方。我对 SQL Profiler 很陌生,所以也许我可以启用一个事件,它会为我提供更多信息来尝试和调试它。有任何想法吗?

我尝试调整 LINQ to SQL 使用的 .dbml 文件中的值。我将InvoiceAuto Generated Value设置为“False”,Auto-Sync设置为“Never”,并Server Data Type设置为“Int NOT NULL”。通常我会将它们分别设置为“True”、“On Insert”和“Int NOT NULL IDENTITY”,但是当我这样做时,我可以看到 SQL Server 正在执行:

SELECT CONVERT(Int,SCOPE_IDENTITY()) 作为 [值]

而不是插入Invoice_ID我提供的。

4

3 回答 3

5

http://msdn.microsoft.com/en-us/library/ms190356.aspx

如果你往下看,你会看到:

如果在存储过程或触发器中运行 SET 语句,则在控制从存储过程或触发器返回后恢复 SET 选项的值。此外,如果在使用 sp_executesql 或 EXECUTE 运行的动态 SQL 字符串中指定了 SET 语句,则在从动态 SQL 字符串中指定的批处理返回控制权后恢复 SET 选项的值。

于 2009-12-30T01:00:46.850 回答
2

虽然 IDENTITY_INSERT 的范围似乎是一个问题,但我在 EF v4.1 中找到并测试的解决方案是首先打开连接,以便会话保持打开状态。例如

using (SiteDataContext context = SiteDataContext.Create())
{
    context.Connection.Open();
    context.ExecuteStoreCommand("SET IDENTITY_INSERT [EnumValue] ON");

    var val = new EnumValue()
    {
        ID = 2000000,
        Value = "just a test",
    };
    context.AddToEnumValues(val);
    context.SaveChanges();

    context.ExecuteStoreCommand("SET IDENTITY_INSERT [EnumValue] OFF");
}

我在没有调用 context.Connection.Open(); 的情况下测试了这个解决方案;首先,它失败了。然后我添加了它完美运行的行。

于 2013-07-05T23:36:54.160 回答
0

我希望 SET IDENTITY_INSERT 的范围是过程的主体。我见过的最常见的方法是创建一个存储过程,它使用 EXEC 来执行包含 SET IDENTITY_INSERT 和 INSERT 本身的动态 SQL。

于 2009-12-30T00:58:59.613 回答