Consider a domain where a Customer, Company, Employee, etc, etc, have a ContactInfo property which in turn contains a set of Address(es), Phone(es), Email(s), etc, etc...
Here is my abbreviated ContactInfo:
public class ContactInfo : Entity<int>
{
public ContactInfo()
{
Addresses = new HashSet<Address>();
}
public virtual ISet<Address> Addresses { get ; private set; }
public Address PrimaryAddress
{
get { return Addresses.FirstOrDefault(a => a.IsPrimary); }
}
public bool AddAddress(Address address)
{
// insure there is only one primary address in collection
if (address.IsPrimary)
{
if (PrimaryAddress != null)
{
PrimaryAddress.IsPrimary = false;
}
}
else
{
// make sure the only address in collection is primary
if (!Addresses.Any())
{
address.IsPrimary = true;
}
}
return Addresses.Add(address);
}
}
Some notes (I am not 100% sure if these are EF "best practices"):
ISet
to insure that there are no duplicate addresses per contactAddAddress
method I can insure that there is always and at most 1 address which is primary....I would like (if possible) to prevent adding Addresses via ContactInfo.Addresses.Add()
method and to force using of ContactInfo.AddAddress(Address address)
...
I am thinking exposing the set of addresses via ReadOnlyCollection
but will this work with Entity Framework (v5)?
How would I go about this?
One way is to make the ICollection property protected and create a new property of IEnumerable that just returns the list of the ICollection property.
The downside with this is that you are not able to query on addresses through the ContactInfo like get all contactinfo that lives in this city.
This is not possible!:
from c in ContactInfos
where c.Addresses.Contains(x => x.City == "New York")
select c
Code:
public class ContactInfo : Entity<int>
{
public ContactInfo()
{
Addresses = new HashSet<Address>();
}
protected virtual ISet<Address> AddressesCollection { get ; private set; }
public IEnumerable<Address> Addresses { get { return AddressesCollection; }}
public Address PrimaryAddress
{
get { return Addresses.FirstOrDefault(a => a.IsPrimary); }
}
public bool AddAddress(Address address)
{
// insure there is only one primary address in collection
if (address.IsPrimary)
{
if (PrimaryAddress != null)
{
PrimaryAddress.IsPrimary = false;
}
}
else
{
// make sure the only address in collection is primary
if (!Addresses.Any())
{
address.IsPrimary = true;
}
}
return Addresses.Add(address);
}
}