【发布时间】:2016-03-09 08:39:18
【问题描述】:
例如,我正在创建发票图表..
图形是用 AnuglarJS 在客户端构建的,然后作为 JSON 发送到后端。在后端,我收到了一个看似完美的对象,由 Web Api 2 中的一些模型绑定魔法创建。
接下来我从 DbContext 加载一个管理实体并将分离的发票添加到它的集合导航属性:
Administration.Lines.Add(invoice);
当触发 DetectChanges 时,图中的每个实体都会获得一个状态为 EntityState.Added 的条目。
从图中我只想添加实体 Invoice 和 InvoiceLines,因为该图的其余部分没有改变。为了完成这项工作,我采用了在本地跟踪状态的方法,例如使用实现 State 属性的 BaseModel 接口(如编程实体框架:DbContext,第 4 章中所建议)。
这一切都非常好......直到例如,当我添加 2 行相同的项目时。出于说明目的,我相信模型绑定器从 JSON 创建对象有点像:
var invoice = new Invoice
{
State = State.Added,
Number = "SALE-001",
Lines =
{
new InvoiceLine
{
State = State.Added,
Price = 10,
Quantity = 1,
Item = new Item { Id = 1, Description = "Product" }
},
new InvoiceLine
{
State = State.Added,
Price = 10,
Quantity = 1,
DiscountPercentage = 50,
Item = new Item { Id = 1, Description = "Product" }
},
}
};
如您所见,这些物品共享相同的 PK,但实际上是不同的对象。因此,当触发 DetectChanges 时,我有 2 个具有相同 PK 的实体 Item 条目,当我尝试使用 InvalidOperationException 将已添加状态转换为未更改时,这一切都会爆炸:
保存或接受更改失败,因为多个“AutomapperWithEF.Data.Domain.Item”类型的实体具有相同的主键值。确保显式设置的主键值是唯一的。确保在数据库和实体框架模型中正确配置了数据库生成的主键。使用实体设计器进行数据库优先/模型优先配置。使用“HasDatabaseGeneratedOption”流式 API 或“DatabaseGeneratedAttribute”进行 Code First 配置。
EF 不应该以某种方式阻止这种情况的发生吗?通过相同类型和PK的相等比较?
编辑:
ChangeTracker.Entries 是触发器的 DbContext:
public class AppContext : DbContext
{
public DbSet<Administration> Administrations { get; set; }
public DbSet<Invoice> Invoices { get; set; }
public DbSet<InvoiceLine> InvoiceLines { get; set; }
public DbSet<Item> Items { get; set; }
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries<BaseModel>())
{
BaseModel baseModel = entry.Entity;
entry.State = ConvertState(baseModel.State);
}
return base.SaveChanges();
}
public static EntityState ConvertState(State state)
{
switch (state)
{
case State.Added:
return EntityState.Added;
case State.Modified:
return EntityState.Modified;
case State.Deleted:
return EntityState.Detached;
default:
return EntityState.Unchanged;
}
}
}
一个例子来说明我的意思:https://github.com/svieillard/SampleEF
【问题讨论】:
-
您能否展示将 Invoice 添加到上下文的代码、触发 DetectChanges 的代码以及将状态从已添加到未更改的代码以及尝试保存更改的代码?
-
我在 GitHub 上添加了 DbContext 和一个指向 example project 的链接来说明问题。它没有客户端JSON发送到后端,但对象创建是必不可少的部分
标签: c# angularjs json entity-framework asp.net-web-api2