繁体   English   中英

首先使用实体​​框架代码保存单个EntityObject

[英]Saving single EntityObject with Entity Framework code first

我在一个项目中使用Entity Framework 6.0.0,首先使用代码和DbContext API。 在我的应用中,有2个具有一对多关系的实体对象,如下所示

class RefTable {
  [Key]
  public int Id { get; set; }
  public string RefName { get; set; }
  public virtual ICollection<Data> DataDetails { get; set; }
}

public class Data
{
    [Key]
    public int Id { get; set; }
    public string RefId { get; set; }
    [ForeignKey("RefId")]
    public virtual RefTable Machine { get; set; }
}

RefTable将在应用程序启动时填充,并且几乎不会进行任何更改。 但是, Data将不时发生变化。

我的Context.cs如下

 public class MyDbContext : DbContext
 {
     public MyDbContext()
         : base("name=CounterDbString")
     {
         Database.SetInitializer<MyDbContext>(new CreateDatabaseIfNotExists<MyDbContext>());
     }

     public DbSet<RefTable> RefData { get; set; }

     public DbSet<Data> Data { get; set; }
 }

我用来保存数据的代码

 public void Write(IList<RefTable> refDataList)
 {
  foreach (var entity in refDataList)
  {
      var element = myContext.RefData.Find(entity.Id);
      if (element == null)
      {
          myContext.RefData.Add(entity);
      }
  }
    myContext.SaveChanges();
 }

 public void Write(IList<Data> dataList)
 {
    myContext.Data.AddRange(dataList);
    myContext.SaveChanges();
 }

当我尝试在第二个函数中执行myContext.SaveChanges()时,总是会收到更新错误,指出violation of Primary Key因为它试图将相同的数据插入RefTable 有没有一种方法可以只保存Data对象中的更改?

当您从DbContext获取实体时,它被认为是附加到上下文的,因此上下文知道您对实体所做的任何更改。 因此,在修改实体后,您不应将其再次添加到DbContext或对其进行特殊处理。 但是,如果实体丢失了它与DbContext的连接或是一个新的连接,则应将其添加到上下文中。

这里可以找到更多有关附着/分离的实体的信息

我仍然看不到完整的代码,但是我认为问题会发生,因为在某些时候某个实体变得未连接,然后被修改,并且当SaveChanges发生时被认为是新实体,从而导致FK错误。

这是一个基本工作原理的小例子:

  private static void Main(string[] args) {
        var db = new MyDbContext();

        var reftable1 = new RefTable() {Id = 100, RefName = "ref1"};
        var listData1 = new List<Data>();
        for (int i=0; i<5; i++)
            listData1.Add(new Data() {Id = i, Machine =  reftable1, RefId = reftable1.Id});
        reftable1.DataDetails = listData1;
        db.RefData.Add(reftable1);

        var reftable2 = new RefTable() {Id = 200, RefName = "ref2"};
        var listData2 = new List<Data>();
        for (int i=5; i<10; i++)
            listData2.Add(new Data() {Id = i, Machine =  reftable2, RefId = reftable2.Id});
        reftable2.DataDetails = listData2;

        db.RefData.Add(reftable2);
        db.SaveChanges();

        db = new MyDbContext(); //lose connection to existing dbContext
        //now reftable1 is unattached, so if not lookup it from new dbContext it will be recreated!!!
        reftable1 = db.RefData.Single(x => x.RefName == "ref1"); //comment to see the difference

        //perform some update
        var data = db.Data.Where(x => x.Id > 7).ToList();
        foreach (var d in data) {
            d.Machine = reftable1;
        }
        db.SaveChanges();

        Console.ReadLine();
    }

而您的班级做了些微改动:

public class RefTable {
    [Key]
    public int Id { get; set; }

    public string RefName { get; set; }

    public virtual ICollection<Data> DataDetails { get; set; }
}

public class Data {
    [Key]
    public int Id { get; set; }

    public int RefId { get; set; }

    [ForeignKey("RefId")]
    public virtual RefTable Machine { get; set; }
}

public class MyDbContext : DbContext {
    public MyDbContext()
        : base("name=CounterDbString") {
        Database.SetInitializer(new CreateDatabaseIfNotExists<MyDbContext>());
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<RefTable>().HasMany(x => x.DataDetails).WithRequired(x => x.Machine);
        base.OnModelCreating(modelBuilder);
    }

    public DbSet<RefTable> RefData { get; set; }

    public DbSet<Data> Data { get; set; }
}

暂无
暂无

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

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