我正在使用Entity Framework 4.1 Code First,并且我有一个具有IDENTITY键的表,因为此表中的所有新条目都应具有自动生成的ID(ID列称为AccountNumber).我需要从此系统的先前版本中导入一些数据 – 这些帐号需要保留.
在a previous question,我了解到必须设置IDENTITY_INSERT才能保留旧帐号.我的想法是,在导入旧客户时,我将打开IDENTITY_INSERT,运行原始sql插入语句,然后将其关闭并使用EF实体正常继续.
所以,我有以下代码:
public const string InsertQuery = "INSERT INTO dbo.Businesses (AccountNumber,Name,Active,CreatedBy,CreatedOn,ModifiedBy,ModifiedOn) VALUES({0},{1},{2},{3},{4},{5},{6})";
…
dbContext.Database.ExecutesqlCommand("SET IDENTITY_INSERT dbo.Businesses ON"); dbContext.Database.ExecutesqlCommand(InsertQuery,customerData.AccountNumber,customerData.Name,customerData.Active,m_userContextManager.GetCurrentUserName(),Now,Now); dbContext.Database.ExecutesqlCommand("SET IDENTITY_INSERT dbo.Businesses OFF"); // load the entity and map the rest of the attributes dbContext.SaveChanges();
当我执行第二个语句时,我得到以下真气错误(因为我只是将它设置为OFF或者我认为):
当IDENTITY_INSERT设置为OFF时,无法在表’Businesses’中为identity列插入显式值.
声明的返回值是-1,但由于the documentation on MSDN for ExecuteSqlCommand真的不合适,我不知道这意味着什么.如果声明由于某种原因失败,我会期望抛出异常.有谁知道这里发生了什么?
解决方法
没有必要使用普通的旧ADO.NET;诀窍是将所有内容打包成一个命令:
public const string InsertQuery = @" SET IDENTITY_INSERT dbo.Businesses ON; INSERT INTO dbo.Businesses (AccountNumber,{6}); SET IDENTITY_INSERT dbo.Businesses OFF; "; dbContext.Database.ExecutesqlCommand(InsertQuery,Now); // load the entity and map the rest of the attributes dbContext.SaveChanges();
此外,您可以删除SET IDENTITY_INSERT dbo.Businesses OFF(因为IDENTITY_INSERT在命令结束时关闭)和dbContext.SaveChanges(),因为ExecutesqlCommand立即执行命令;它不等待SaveChanges().