0

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; }
        }
    }
user702769
  • 2,435
  • 2
  • 25
  • 34

2 Answers2

1

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; }
    }
}
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • You are correct. Reason why your suggestion didn't work is because one of the properties wasn't marked virtual. Anyhow, are you sure reason why automatic relationship fix-up doesn't work is due to calling value.List()? Please see my edit – user702769 Oct 27 '11 at 16:05
  • Won't bother you again, but just in case you find the time ... could you see my edit? – user702769 Oct 31 '11 at 19:11
  • 1
    No. Properties must have setter to make them work in correct way. – Ladislav Mrnka Oct 31 '11 at 19:18
0

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.

Pando
  • 1,079
  • 1
  • 9
  • 13