EF 7身份插入问题

时间:2016-08-18 17:11:31

标签: entity-framework entity-framework-core

我必须能够在我的列表“final_zones”中设置我想要添加的实体的主键。我有一个控制器构造函数如下:

    public UtilController(CFETSContext context)
    {
        _context = context; 
    }
     ......Then in a web api method.........
        using (var transaction = _context.Database.BeginTransaction())
        {
            _context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON");             

            _context.SaveChanges();
            transaction.Commit();
        }


       using (var transaction = _context.Database.BeginTransaction())
        {             
            _context.Zones.AddRange(final_zones);
            _context.SaveChanges(); //ERROR HERE
            transaction.Commit();
        }

无论我做什么,我似乎都无法启用IDENTITY_INSERT。我收到以下错误:

{"Cannot insert explicit value for identity column in table 'Zone' when IDENTITY_INSERT is set to OFF."}

我似乎无法让它关闭。我可以在控制器中向我的数据库添加实体,所以我知道其他一切都在工作。我已尝试在没有交易的情况下执行此操作,但结果相同。

 _context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON"); 
_context.Zones.AddRange(final_zones);
        _context.SaveChanges();

有什么想法吗?我不知道下一步该尝试什么。感谢。

2 个答案:

答案 0 :(得分:4)

我解决了以下问题:

       using (var dbContextTransaction = _context.Database.BeginTransaction())
        {
            try
            {
                _context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON");
                _context.Zones.AddRange(final_zones);
                _context.SaveChanges();          

                dbContextTransaction.Commit();
            }
            catch (Exception e)
            {
                dbContextTransaction.Rollback();
            }
        }

注意:您必须为每个表执行此操作。 IDENTITY_INSERT一次只能为1个表设置,所以你可以这样做,或者在同一个事务中将它切换为OFF。

此外,IDENTITY_INSERT必须在交易中,因为它只在交易期间保持开启状态。

答案 1 :(得分:1)

SET IDENTITY_INSERT语句的范围限定为一个SQL会话,这实际上等同于通过开放连接发送的一组语句。

但是,默认情况下,EF上下文将打开并关闭每个单个语句的连接,并执行数据库交互。因此,在ExecuteSqlCommand语句之后,连接已关闭,并且IDENTITY_INSERT已重置。

现在,如果在上下文执行语句之前打开它,EF 将不会关闭连接,这是一个隐藏的功能。所以,如果你这样做......

try
{
    _context.Database.Connection.Open();
    _context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON");
    _context.Zones.AddRange(final_zones);
    _context.SaveChanges();
}
finally
{
    _context.Database.Connection.Close();
}

...您会注意到IDENTITY_INSERT设置将“存活”ExecuteSqlCommand声明。