How to turn on identity-insert in .net core

后端 未结 9 1251
日久生厌
日久生厌 2020-12-15 07:12

I made a few tables in EF and entered in some seed data where I give value to a few columns with a primary key. When I run the application I am getting the error message: <

9条回答
  •  有刺的猬
    2020-12-15 08:08

    Steve Nyholm's answer works fine, but I will provide some extra explanation and some generic code with exception handling.

    Normally the context takes care of the transaction, but in this case manually taking care of it is required. Why?

    Database context will generate a BEGIN TRAN after the SET IDENTITY_INSERT is issued. This will make transaction's inserts to fail since IDENTITY_INSERT seems to affect tables at session/transaction level.

    So, everything must be wrapped in a single transaction to work properly.

    Here is some useful code to seed at key level (as opposed to table level):

    Extensions.cs

    [Pure]
    public static bool Exists(this DbSet dbSet, params object[] keyValues) where T : class
    {
        return dbSet.Find(keyValues) != null;
    }
    
    public static void AddIfNotExists(this DbSet dbSet, T entity, params object[] keyValues) where T: class
    {
        if (!dbSet.Exists(keyValues))
            dbSet.Add(entity);
    }
    

    DbInitializer.cs

    (assumes that model class name is the same as table name)

    private static void ExecuteWithIdentityInsertRemoval(AspCoreTestContext context, Action act) where TModel: class
    {
        using (var transaction = context.Database.BeginTransaction())
        {
            try
            {
                context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT " + typeof(TModel).Name + " ON;");
                context.SaveChanges();
                act(context);
                context.SaveChanges();
                transaction.Commit();
            }
            catch(Exception)
            {
                transaction.Rollback();
                throw;
            }
            finally
            {
                context.Database.ExecuteSqlCommand($"SET IDENTITY_INSERT " + typeof(TModel).Name + " OFF;");
                context.SaveChanges();
            }
        }
    }
    
    public static void Seed(AspCoreTestContext context)
    {
        ExecuteWithIdentityInsertRemoval(context, ctx =>
        {
            ctx.TestModel.AddIfNotExists(new TestModel { TestModelId = 1, ModelCode = "Test model #1" }, 1);
            ctx.TestModel.AddIfNotExists(new TestModel { TestModelId = 2, ModelCode = "Test model #2" }, 2);
        });
    }
    

提交回复
热议问题