Entity Framework 4.2, Unable to set Identity Insert ON

时间:2015-09-01 21:42:50

标签: c# asp.net asp.net-mvc ado.net entity-framework-4.1

I would like to add records in bulk to a table with given ID's so I could build a hierarchy for displaying records in a tree view fashion. I can singly add records which works fine and I don't set the ID. I would like to set the Ids only in bulk so I set the DatabaseGenerated Option as None in the id column for my entity as None.

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{

     foreach (ErrorCode ec in errorCodesStep3.errorcodesUsers)
     {

           errorCode.ID = ec.ID;
           errorCode.ParentID = ec.ParentID;
           errorCode.ErrorDescription = ec.ErrorDescription;
           db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.ErrorCode ON");
           db.ErrorCode.Add(errorCode);
           db.SaveChanges();    
           scope.Complete();
     }
}

ErrorCode

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }

I am getting the error that:

cannot set identity when identity insert is OFF.

Not sure whats wrong, since I have seen examples that identity insert can be switched on. I am using EF Version 4.2.0.0 and Runtime Version v4.0.30319. I can easily add an INSERT statement via executeSQL with parameterized variables but I would like to do it with entity framework. Seems like db.Database.ExecuteSqlCommand is in a separate scope and it closed right away and is not available when db.savechanged is executed.

3 个答案:

答案 0 :(得分:1)

试试这个:Entity Framework with Identity Insert

也许是这样:

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
    using (var db = new Context()) // your Context
    {
        db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.ErrorCode ON");
        ErrorCode errorCode = db.ErrorCode.First(); // for example
        foreach (ErrorCode ec in errorCodesStep3.errorcodesUsers)
        {
            errorCode.ID = ec.ID;
            errorCode.ParentID = ec.ParentID;
            errorCode.ErrorDescription = ec.ErrorDescription;    
            db.ErrorCode.Add(errorCode);
        }
        db.SaveChanges();
        db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.ErrorCode OFF");
        scope.Complete();
    }
}

答案 1 :(得分:0)

以下是我验证过您想要的代码。想法是对ExecuteSqlCommand和insert操作使用单个连接,看起来BeginTransaction()调用就可以了:

using (var db = new TestEntities()) { 
    using (var tran = db.Database.BeginTransaction()) {
       db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Error ON");
            foreach (var id in Enumerable.Range(1, 20)) {
                var ec = new Error();
                ec.ErrorID = id;
                db.Errors.Add(ec);
            }
            db.SaveChanges();
            db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Error OFF");
            tran.Commit();
        }
    }
}

答案 2 :(得分:0)

添加另一列以管理层次结构。标识列不应用于此目的。

很抱歉没有回答这个问题,但我认为你的解决方案不对。