POCO代理无法自动设置关系

时间:2011-10-26 18:10:24

标签: entity-framework-4 entity-relationship

更改跟踪代理的其中一个要求是,表示关系“很多”端的导航属性必须返回实现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确实返回一个实现ICollectionList<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; }
        }
    }

2 个答案:

答案 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(而不是使用CreateObjectCreate方法)创建实体时,POCO类中的地址集合也会自动实例化在代理不受欢迎的情况下(例如序列化)。

另一个变化是ICollection被实现为HashSet&lt;&gt;而不是List&lt;&gt;,确保唯一性。