简体   繁体   English

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

[英]Saving single EntityObject with Entity Framework code first

I am using Entity Framework 6.0.0 in a project, using code first and the DbContext API. 我在一个项目中使用Entity Framework 6.0.0,首先使用代码和DbContext API。 In my app, there are 2 entity objects which has one-to-many relationship as shown below 在我的应用中,有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; }
}

The RefTable will be populated on application startup and will barely undergo change. RefTable将在应用程序启动时填充,并且几乎不会进行任何更改。 However Data will undergo change from time to time. 但是, Data将不时发生变化。

My Context.cs is as below 我的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; }
 }

The code I am using to save data 我用来保存数据的代码

 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();
 }

When I try to perform myContext.SaveChanges() in the second function, I always get update error saying violation of Primary Key as it is trying to insert the same data into RefTable . 当我尝试在第二个函数中执行myContext.SaveChanges()时,总是会收到更新错误,指出violation of Primary Key因为它试图将相同的数据插入RefTable Is there a way to save only the changes in Data object? 有没有一种方法可以只保存Data对象中的更改?

When you are getting entity from DbContext it's considered to be attached to context, so context is aware of any change you are doing with the entity. 当您从DbContext获取实体时,它被认为是附加到上下文的,因此上下文知道您对实体所做的任何更改。 So after modifying the entity you should not add it again to DbContext or do something special about it. 因此,在修改实体后,您不应将其再次添加到DbContext或对其进行特殊处理。 But if entity loses it's connection do DbContext or is a new one, it should be added to the context. 但是,如果实体丢失了它与DbContext的连接或是一个新的连接,则应将其添加到上下文中。

Some more reading about attached/detached entites can be found here . 这里可以找到更多有关附着/分离的实体的信息

I still cannot see full code, but I think the problem happens because at some point some entity becomes unattached, then is modified and when SaveChanges occurs is considered to be new one, causing FK error. 我仍然看不到完整的代码,但是我认为问题会发生,因为在某些时候某个实体变得未连接,然后被修改,并且当SaveChanges发生时被认为是新实体,从而导致FK错误。

Here is a small example of how it should basically work: 这是一个基本工作原理的小例子:

  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();
    }

And your classes with minor changes: 而您的班级做了些微改动:

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