我正在使用Entity Framework 6.当我将导航属性更新为对象然后执行SaveChanges(),而不是引用现有的对象时,它会在引用表中创建副本。
我在下面有一些例子:
以下示例按预期工作。它创建了一个“客户”和一个“订单”,并成功地将它们联系起来:
// Homer Simpson buys some Duff beer
Console.WriteLine("Homer Simpson is buying Duff beer");
Customer customer = new Customer
{
Name = "Homer Simpson"
};
Order order1 = new Order
{
Description = "Duff Beer"
};
customer.Orders.Add(order1);
using (EFContext db = new EFContext())
{
db.Customers.Add(customer);
DisplayChanges(db);
db.SaveChanges();
}
输出
Homer Simpson is buying Duff beer
ConsoleApplication1.Objects.Customer - Added
ConsoleApplication1.Objects.Order - Added
但是,如果我尝试添加订单并关联现有客户,当我保存更改时,它会复制数据库中的Customer对象以及我创建的现有订单:
// Homer Simpson buys some Duff beer
Console.WriteLine("Homer Simpson is buying Duff beer");
Customer customer = new Customer
{
Name = "Homer Simpson"
};
Order order1 = new Order
{
Description = "Duff Beer"
};
customer.Orders.Add(order1);
using (EFContext db = new EFContext())
{
db.Customers.Add(customer);
DisplayChanges(db);
db.SaveChanges();
}
// Homer Simpson buys some Buzz Cola
Console.WriteLine("\r\nHomer Simpson is buying Buzz Cola");
Order order2 = new Order
{
Description = "Buzz Cola",
Customer = customer
};
using (EFContext db = new EFContext())
{
db.Orders.Add(order2);
DisplayChanges(db);
db.SaveChanges();
}
输出
Homer Simpson is buying Duff beer
ConsoleApplication1.Objects.Customer - Added
ConsoleApplication1.Objects.Order - Added
Homer Simpson is buying Buzz Cola
ConsoleApplication1.Objects.Order - Added
ConsoleApplication1.Objects.Customer - Added
ConsoleApplication1.Objects.Order - Added
如果我设置外键而不是导航属性,则记录不会重复。但是,在这种情况下,在显式加载之前,我无法访问相关对象的属性:
// Homer Simpson buys some Duff beer
Console.WriteLine("Homer Simpson is buying Duff beer");
Customer customer = new Customer
{
Name = "Homer Simpson"
};
Order order1 = new Order
{
Description = "Duff Beer"
};
customer.Orders.Add(order1);
using (EFContext db = new EFContext())
{
db.Customers.Add(customer);
DisplayChanges(db);
db.SaveChanges();
}
// Homer Simpson buys some donuts
Console.WriteLine("\r\nHomer Simpson is buying donuts");
Order order3 = new Order
{
Description = "Donuts",
CustomerID = 1
};
if (order3.Customer == null)
{
Console.WriteLine("Customer is null before save!");
}
else
{
Console.WriteLine("The customer is " + customer.Name + " before save!");
}
using (EFContext db = new EFContext())
{
db.Orders.Add(order3);
DisplayChanges(db);
db.SaveChanges();
}
if (order3.Customer == null)
{
Console.WriteLine("Customer is null after save!");
}
else
{
Console.WriteLine("The customer is " + customer.Name + " after save!");
}
using (EFContext db = new EFContext())
{
db.Orders.Attach(order3);
db.Entry(order3).Reference(x => x.Customer).Load();
}
if (order3.Customer == null)
{
Console.WriteLine("Customer is null after forced load!");
}
else
{
Console.WriteLine("The customer is " + customer.Name + " after forced load!");
}
输出
Homer Simpson is buying Duff beer
ConsoleApplication1.Objects.Customer - Added
ConsoleApplication1.Objects.Order - Added
Homer Simpson is buying donuts
Customer is null before save!
ConsoleApplication1.Objects.Order - Added
Customer is null after save!
The customer is Homer Simpson after forced load!
有人能提供任何建议吗?我知道您可以手动附加和分离实体,但话虽如此,我正在处理一些非常复杂的对象。我想找到一种简单的方法来控制实体框架中的变更跟踪。
此致
Peter Deegan
答案 0 :(得分:0)
当您附加客户对象到订单2时,它会插入一个新的客户对象,我认为您应该始终使用外键而不是附加实体,并且用于加载属性部分,当然,您不会将客户对象附加到订单上,因为您刚刚插入它
如果您检查public virtual <T> Add(T entity)
,因为您可以看到它返回对象本身,而不包括任何其他对象,客户对象将不会加载,直到您加载它有意义我猜,在您的示例中您使用显式加载加载客户对象,如果要避免可以启用延迟加载并始终获取客户对象而不显式加载它。简而言之,总是使用fk,当你需要实体加载它(延迟加载或显式)时,附加对象绝不是好习惯,除非你想要将它们全部插入,或者你不关心重复。
我希望这有帮助。