2016-08-16 106 views
0

我在項目中使用實體框架6.0.0,首先使用代碼和DbContext API。在我的應用程序,還有一些有一個一對多的關係,2個實體對象如下圖所示首先使用實體​​框架代碼保存單個EntityObject

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對象中的更改?

+2

顯示代碼/改變實體保存之前。 – 3615

+0

更新了上面的問題。 – SohamC

+0

你需要顯示調用'Write'的代碼 - 你如何獲得作爲參數傳遞的實體。 「Write」都沒有錯,問題在於你稱之爲後者的地方。 –

回答

0

當您從DbContext獲取實體時,它被認爲是附加到上下文的,因此上下文知道您正在對該實體進行的任何更改。所以在修改實體之後,你不應該再次將它添加到DbContext中,或者對它做些特別的事情。但是如果實體失去了它的連接DbContext或者是一個新的,它應該被添加到上下文中。

可以找到關於附加/分離物的更多閱讀內容here

我仍然看不到完整的代碼,但我認爲問題的發生是因爲在某些時候某些實體變爲未連接,然後被修改,並且發生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; } 
} 
相關問題