繁体   English   中英

通过EF代码优先迁移仅用于初始数据的身份插入

[英]Identity Insert just for initial Data with EF Code-First Migrations

我目前正在尝试将一些本地数据带入使用EF Code-First迁移的数据库中。 这些数据已经具有唯一的ID,因此最初应按原样插入数据的第一个“集合”。

现在,我考虑首先设置“ DatabaseGeneratedOption.None”,将数据集添加到数据库,计算上次使用的ID,然后使用T-SQL命令“ dbcc checkident(表名,种子,[NEW AUTO ID] )”,然后添加另一个迁移,同时将GeneratedOption重置为“ DatabaseGeneratedOption.Identity”。

这是正确的方法,甚至是可能的,还是我走错了路?

任何线索将不胜感激
最好的祝福

编辑-米歇尔答案

试图实现Michals答案,但ID仍由数据库“生成”,并且我的显式值被忽略。 也许这是我插入值的方式:

MyDbContext context = // GetContext;
DbSet<SomeClass> dbSet = context.SomeClass;
context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT " + someClassTableName + " ON");

foreach(SomeClass sc in toAdd)
{
    // sc already contains all data including its unique ID
    sbSet.Add(sc);
}

context.SaveChanges();
context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT " + someClassTableName + " OFF");

解决方案/ w Michals答案

好吧,我尽了最大努力以不同的方式实现了米哈尔斯的答案,最后得出了一个(真的很奇怪)的解决方案。

首先,我有我的DBContext类,然后是一个名为DBContextEditor的派生类。 所做的就是覆盖我更改所有“身份”属性的OnModelCreating。

public class MyContextEditor : MyContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<SomeClass>()
        .Property(e => e.ID)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }
}

最终,结合使用该类和其他文章(来自以下s。资料来源)的其他一些技术,我得到了想要的结果。
终于我有了这样的事情:

MyContext context = new MyContextEditor();
DbSet<SomeClass> dataSet = context.SomeClass;

// this.Clear(dataSet); Just for testing to reset Identity Auto ID and remove all Data
// this.Reset(dataSet);

context.Database.Connection.Open();
// Add data to dataSet...
// dataSet.Add(toAdd);
// Apply Michals answer and save
context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT " + tableName + " ON");
context.SaveChanges();
context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT " + tableName + " OFF");

// Close Connection
context.Database.Connection.Close();

我还尝试实现覆盖了MyContext类的重写,结果以一个错误说“烘焙模型不同...”而结束,这也将ID属性更改为不再是“身份”。

最后,这种方法使我对添加身份数据具有所需的控制权,同时保持了生成身份值的可能性。 此外,任何进一步的迁移都不会更改模型,也不会删除“ Identity”标志,而[DatabaseGeneratedOption]确实删除了它。 还可以并建议将其存储在如下使用中:

using( var transaction = context.Database.BeginTransaction'))

仅供参考伪代码中的模型

class SomeClass
{
    [Key]
    public int ID { get; set; }

    public string Title { get; set; }
    // More Properties
}

相关文章和来源

我个人要做的事情如下:

  1. SET IDENTITY_INSERT sometableWithIdentity ON
  2. 播种所有数据
  3. SET IDENTITY_INSERT sometableWithIdentity OFF

播种数据时,我将所有实体附加到上下文中,并添加为先前存在的ID。

有时唯一的问题是是否有外键的循环引用。 为了解决这个问题,我删除了外键的一侧,添加了所有实体,然后将外键放回去。

例如,如果我有以下情况:

public class Customer 
{
    public List<Address> Addresses { get; set; }

    public long? DefaultAddressId { get; set; }
    public Address DefaultAddress { get; set; }
}

public class Customer 
{
    public long Id { get; set; }

    public long CustomerId { get; set; }
    public Customer Customer { get; set; }
}

我将执行以下操作:

  1. 取消插入Customer.DefaultAddressId
  2. Customer + Address es附加为EntityState.New
  3. Context.SaveChanges()保存到数据库
  4. 重新附加Customer.DefaultAddressId以从步骤2开始跟踪客户
  5. Context.SaveChanges()保存默认地址的

另一个选择是在可能的情况下关闭种子期间的参照完整性。 但是,由于我们使用多个数据库(Sqlite用于本地开发,PostegreSql用于产品,有时甚至是MariaDb),因此我们无法成功将其关闭+重新打开+强制检查是否存在参照完整性/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM