开发者

Saving Entity causes duplicate insert into lookup data

I am using EF 4.1 "code first" to create my db and objects.

Given:

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; }
}

An order has one ordertype. An order type is just a look up table. The values dont change. Using 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(); 

Now in our App we load all our lookup data and cache it.

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();

Our you-beaut order is saved but with a n开发者_如何学编程ew order type, courtesy of EF. So now we have two same order types in our database. What can I do to alter this behaviour?

TIA


With EF 4.1 you can do this before calling SaveChanges:

db.Entry(order.OrderType).State = EntityState.Unchanged;


Alternatively to Yakimych's solution you can attach the OrderType to the context before you add the order to let EF know that the OrderType already exists in the database:

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 - thanks for the answers. Interestingly I tried both ways and neither worked. Hence I asked the question. Your answers confirmed that I must be doing something wrong, and sure enough I wasnt managing my dbContext properly.

Still its a pain that EF automatically wants to insert lookup/static data even when you supply the full object (including the lookups unique Id). It puts the onus on the developer to remember to set the state. To make things a little easier I do:

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;
}  

in SaveChanges override.

Again thanks for the help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜