[英]Entity Framework read only collections
考慮一個客戶,公司,員工等具有ContactInfo屬性的域,該屬性又包含一組地址,電話,電子郵件等等......
這是我的縮寫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);
}
}
一些注釋(我不是100%確定這些是EF“最佳實踐”):
ISet
以確保每個聯系人沒有重復的地址 AddAddress
方法我可以確保總是最多1個地址是主要的.... 我希望(如果可能的話)阻止通過ContactInfo.Addresses.Add()
方法添加地址並強制使用ContactInfo.AddAddress(Address address)
...
我正在考慮通過ReadOnlyCollection
公開地址集,但這是否適用於Entity Framework(v5)?
我該怎么做?
Edo van Asseldonk建議的另一個選項是創建一個從Collection繼承其行為的自定義集合。
您必須為ISet制作自己的實現,但原理是相同的。
通過隱藏修改列表並將其標記為過時的任何方法,您可以有效地獲得ReadOnlyCollection,但是當它取消裝箱為Collection時,EF仍然可以修改它。 在我的版本中,我為List添加了一個隱式運算符轉換,因此我們不必在添加項時取消收集集合:
var list = ListProperty.ToList();
list.Add(entity)
ListProperty = list;
哪里
public virtual EntityCollection<MyEntity> ListProperty { get; protected set; }
這是EntityCollection:
public class EntityCollection<T> : Collection<T>
{
[Obsolete("Unboxing this collection is only allowed in the declarating class.", true)]
public new void Add(T item) { }
[Obsolete("Unboxing this collection is only allowed in the declarating class.", true)]
public new void Clear() { }
[Obsolete("Unboxing this collection is only allowed in the declarating class.", true)]
public new void Insert(int index, T item) { }
[Obsolete("Unboxing this collection is only allowed in the declarating class.", true)]
public new void Remove(T item) { }
[Obsolete("Unboxing this collection is only allowed in the declarating class.", true)]
public new void RemoveAt(int index) { }
public static implicit operator EntityCollection<T>(List<T> source)
{
var target = new EntityCollection<T>();
foreach (var item in source)
((Collection<T>) target).Add(item); // unbox
return target;
}
}
這樣您仍然可以像往常一樣運行Linq,但在嘗試修改Collection屬性時會得到正確的使用警告。 將它解壓縮到集合將是唯一的方法:
((Collection<MyEntity>)ListProperty).Add(entity);
一種方法是保護ICollection屬性並創建IEnumerable的新屬性,該屬性只返回ICollection屬性的列表。
這樣做的缺點是您無法通過ContactInfo查詢地址,例如獲取位於此城市的所有contactinfo。
這是不可能的!:
from c in ContactInfos
where c.Addresses.Contains(x => x.City == "New York")
select c
碼:
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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.