“保存实体”会导致对查找数据的重复插入

本文关键字:数据 查找 插入 实体 保存 保存实体 | 更新日期: 2023-09-27 17:50:12

我使用EF 4.1 "代码优先"来创建我的数据库和对象。

给定

:

public class Order 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual OrderType OrderType { get; set; }
}
public class OrderType 
{
    public int Id { get; set; }
    public string Name { get; set; }
}

一个订单有一个订单类型。订单类型只是一个查找表。值不会改变。使用Fluent API:

//Order
ToTable("order");
HasKey(key => key.Id);
Property(item => item.Id).HasColumnName("order_id").HasColumnType("int");
Property(item => item.Name).HasColumnName("name").HasColumnType("string").HasMaxLength(10).IsRequired();
HasRequired(item => item.OrderType).WithMany().Map(x => x.MapKey("order_type_id")).WillCascadeOnDelete(false);
//OrderType
ToTable("order_type");
HasKey(key => key.Id);
Property(item => item.Id).HasColumnName("order_type_id").HasColumnType("int");
Property(item => item.Name).HasColumnName("name").HasColumnType("nvarchar").HasMaxLength(100).IsRequired(); 

现在,在我们的应用程序中,我们加载所有的查找数据并缓存它。

var order = new Order
{
   Name = "Bob"
   OrderType = GetFromOurCache(5) //Get order type for id 5
};
var db = _db.GetContext();
db.Order.Add(order);
db.SaveChanges();

我们的you- beauty订单被保存了,但有了新的订单类型,这是EF提供的。现在我们的数据库中有两种相同的订单类型。我能做些什么来改变这种行为?

TIA

“保存实体”会导致对查找数据的重复插入

使用EF 4.1,您可以在调用SaveChanges:

之前执行此操作。
db.Entry(order.OrderType).State = EntityState.Unchanged;

对于Yakimych的解决方案,您可以在添加订单之前将附加 OrderType到上下文,以让EF知道OrderType已经存在于数据库中:

var order = new Order
{
    Name = "Bob"
    OrderType = GetFromOurCache(5) //Get order type for id 5
};
var db = _db.GetContext();
db.OrderTypes.Attach(order.OrderType);
db.Order.Add(order);
db.SaveChanges();

Yakimych/Slauma -谢谢你的回答。有趣的是,两种方法我都试过了,但都不奏效。于是我问了这个问题。你的回答证实了我一定是做错了什么,当然我没有正确管理我的dbContext。

仍然是一个痛苦的EF自动想要插入查找/静态数据,即使你提供了完整的对象(包括查找的唯一Id)。它让开发人员有责任记住设置状态。为了让事情简单一点,我这样做:

var properties = entry.GetType().GetProperties().Where(x => x.PropertyType.GetInterface(typeof(ISeedData).Name) != null);
foreach (var staticProperty in properties)
{
    var n = staticProperty.GetValue(entry, null);
    Entry(n).State = EntityState.Unchanged;
}  

在SaveChanges覆盖。

再次感谢您的帮助。