更改跟踪代理的其中一个要求是,表示关系“很多”端的导航属性必须返回实现ICollection
的类型。
更改跟踪代理还提供了自动关系修复的类。例如,执行someEmployee.Addresses.Add(address);
时,代理会自动将address.EmployeeID
设置为100
的值,并将someEmployee
实例分配给导航属性address.Employee
:
public class Employee
{
public virtual int EmployeeID { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
Employee someEmployee = ...;
Address address = ...;
Console.WriteLine(someEmployee.EmployeeID); // 100
Console.WriteLine(address.EmployeeID); // 20
someEmployee.Addresses.Add(address);
Console.WriteLine(address.EmployeeID); // 100
Console.WriteLine(address.Employee.EmployeeID); // 100
但是如果我们更改Employee类的定义,那么由于某种原因,代理无法自动修复关系:
public class Employee
{
private List<Address> _addresses = new List<Address>();
public virtual int EmployeeID { get; set; }
public virtual ICollection<Address> Addresses
{
get { return _addresses; }
set { _addresses = value.ToList(); }
}
}
Console.WriteLine(someEmployee.EmployeeID); // 100
Console.WriteLine(address.EmployeeID); // 20
someEmployee.Addresses.Add(address);
Console.WriteLine(address.EmployeeID); // 20
Console.WriteLine(address.Employee.EmployeeID); // 20
导航属性Employee.Addresses
确实返回一个实现ICollection
(List<T>
)的类型,那么为什么代理不能修复关系呢?
谢谢
修改
这是因为代理本身并没有修复关系。它用你自己的实例替换你的实例化集合,但是一旦你调用了value.ToList(),你就会用修正逻辑丢弃它的实现。
但是,如果调用value.ToList()
是自动关系修复不起作用的原因,那么删除setter
方法应启用自动关系修复,但它不会:
public class Employee
{
private List<Address> _addresses = new List<Address>();
public virtual int EmployeeID { get; set; }
public virtual ICollection<Address> Addresses
{
get { return _addresses; }
}
}
答案 0 :(得分:1)
这是因为代理本身并没有修复关系。它用自己的实例替换了你的实例化集合,但是一旦你调用value.ToList()
,你就会用修复逻辑丢弃它的实现。改为使用它,它应该按预期工作:
public class Employee
{
public ICollection<Address> addresses = new List<Address>();
public virtual int EmployeeId { get; set; }
public virtual ICollection<Address> Addresses
{
get { return addresses; }
set { addresses = value; }
}
}
答案 1 :(得分:0)
你也可以试试这个:
public class Employee {
private ICollection<Address> _addresses = new HashSet<Address>();
public virtual int EmployeeID { get; set; }
public virtual ICollection<Address> Addresses {
get { return _addresses ?? (_addresses = new HashSet<Address>()); }
protected set { _addresses = value; }
}
}
优点是,当您使用new
(而不是使用CreateObject或Create方法)创建实体时,POCO类中的地址集合也会自动实例化在代理不受欢迎的情况下(例如序列化)。
另一个变化是ICollection被实现为HashSet&lt;&gt;而不是List&lt;&gt;,确保唯一性。