POCO代理无法自动设置关系

发布于 2024-12-12 05:19:00 字数 2113 浏览 3 评论 0原文

更改跟踪代理的要求之一是表示关系“多”端的导航属性必须返回实现 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 ),那么为什么代理不能修复关系?

谢谢

编辑

这是因为代理本身没有修复关系。它会用自己的实例化集合替换您的实例化集合,但是一旦您调用 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; }
        }
    }

One of the requieremets for change tracking proxies is that a navigation property that represents the "many" end of a relationship must return a type that implements ICollection.

Change tracking proxies also provide classes with automatic relationship fix-up. For example, when someEmployee.Addresses.Add(address); is executed, proxy automatically sets address.EmployeeID to value of 100 and also assigns someEmployee instance to a navigation property 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

But if we change the definition of Employee class, then for some reason proxy isn't able to automatically fix-up the relationship:

    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

Navigation property Employee.Addresses does return a type that implements ICollection ( List<T> ), so why isn't proxy able to fix-up the relationship?

Thank you

EDIT

It is because the proxy itself doesn't fixup the relation. It replaces your instantiated collections with its own but once you call value.ToList() you are throwing away its implementation with fixup logic.

But if calling value.ToList() is the reason why automatic relationship fix-up doesn't work, then removing the setter method should enable automatic relationship fix-up, but it doesn't:

    public class Employee
    {
        private List<Address> _addresses = new List<Address>();

        public virtual int EmployeeID { get; set; }

        public virtual ICollection<Address> Addresses 
        {
            get { return _addresses; }
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

用心笑 2024-12-19 05:19:00

这是因为代理本身并没有修复关系。它用自己的实例化集合替换了您的实例化集合,但是一旦您调用 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; }
    }
}

It is because the proxy itself doesn't fixup the relation. It replaces your instantiated collections with its own but once you call value.ToList() you are throwing away its implementation with fixup logic. Use this instead and it should work as expected:

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; }
    }
}
太傻旳人生 2024-12-19 05:19:00

您也可以尝试这样做:

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 创建实体时,POCO 类中的 Addresses 集合也会自动实例化(而不是使用 CreateObject创建方法)用于不需要代理的情况(例如序列化)。

另一个变化是ICollection被实现为HashSet<>。而不是 List<>,确保唯一性。

You can also try this:

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

The advantage is that the Addresses collection in the POCO class will also be automatically instantiated when you create your entity with new (rather than using the CreateObject or Create methods) for use in situations where proxies are undesirable (e.g. serialization).

Another change is that the ICollection is implemented as a HashSet<> instead of a List<>, ensuring uniqueness.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文