首先使用实体框架代码保存单个实体对象
Posted
技术标签:
【中文标题】首先使用实体框架代码保存单个实体对象【英文标题】:Saving single EntityObject with Entity Framework code first 【发布时间】:2016-08-16 11:27:18 【问题描述】:我在一个项目中使用 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
对象中的更改?
【问题讨论】:
在保存之前显示如何获取/更改实体的代码。 更新了上面的问题。 您需要显示调用Write
的代码 - 您如何获取作为参数传递的实体。 Write
s 都没有问题,问题出在你称之为后者的地方。
【参考方案1】:
当您从 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;
【讨论】:
以上是关于首先使用实体框架代码保存单个实体对象的主要内容,如果未能解决你的问题,请参考以下文章