entity framework只读集合
考虑一个客户,公司,员工等具有ContactInfo属性的域,该属性又包含一组地址,电话,电子邮件等等……
这是我的缩写ContactInfo:
public class ContactInfo : Entity { public ContactInfo() { Addresses = new HashSet(); } public virtual ISet 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“最佳实践”):
- Address(es)的集合是虚拟的,允许延迟加载
- 私人二手集合禁止收集更换
- 集合是一个
ISet
以确保每个联系人没有重复的地址 - 使用
AddAddress
方法我可以确保总是最多1个地址是主要的….
我希望(如果可能的话)阻止通过ContactInfo.Addresses.Add()
方法添加地址并强制使用ContactInfo.AddAddress(Address address)
…
我正在考虑通过ReadOnlyCollection
公开地址集,但这是否适用于Entity Framework(v5)?
我怎么会这样呢?
一种方法是保护ICollection属性并创建IEnumerable的新属性,该属性只返回ICollection属性的列表。
这样做的缺点是您无法通过ContactInfo查询地址,例如获取此城市中的所有contactinfo。
这是不可能的!:
from c in ContactInfos where c.Addresses.Contains(x => x.City == "New York") select c
码:
public class ContactInfo : Entity { public ContactInfo() { Addresses = new HashSet(); } protected virtual ISet AddressesCollection { get ; private set; } public IEnumerable 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); } }
Edo van Asseldonk建议的另一个选项是创建一个自定义集合,从Collectioninheritance其行为。
您必须为ISet制作自己的实现,但原则是相同的。
通过隐藏修改列表并将其标记为过时的任何方法,您可以有效地获得ReadOnlyCollection,但是当它取消装箱为Collection时,EF仍然可以修改它。 在我的版本中,我为List添加了一个隐式运算符转换,因此我们不必在添加项时取消收集集合:
var list = ListProperty.ToList(); list.Add(entity) ListProperty = list;
哪里
public virtual EntityCollection ListProperty { get; protected set; }
这是EntityCollection:
public class EntityCollection : Collection { [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 (List source) { var target = new EntityCollection (); foreach (var item in source) ((Collection ) target).Add(item); // unbox return target; } }
这样您仍然可以像往常一样运行Linq,但在尝试修改Collection属性时会得到正确的使用警告。 将它解压缩到集合将是唯一的方法:
((Collection)ListProperty).Add(entity);
- UserPrincipal.GetGroups与UserPrincipal.GetAuthorizationGroups?
- 如何禁用ASP.NET的自动注销function
- 如何使用JSON.Net读取JSON并输出HTML?
- DllNotFoundException,但DLL就在那里
- Sequence包含多个匹配元素 – 使用Entiity Framework添加项目
- Docker在VS中运行但在发布到AWS时出错? 错误CS5001:程序不包含适用于入口点的静态“主”方法
- 协同程序为何停止工作/执行
- DPI无法正确缩放
- nHibernate Validator自定义IMessageInterpolator