[英]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.