c# - Entity Framework 只读集合

标签 c# entity-framework ef-code-first readonly-collection

考虑一个域,其中客户、公司、员工等具有 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 的“最佳实践”):

  • 地址集合是虚拟的以允许延迟加载
  • collection 的 private setter 禁止替换 collection
  • 集合是一个 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);

关于c# - Entity Framework 只读集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11191103/

相关文章:

c# - 为什么有时无法解析虚拟化数据网格中的相对绑定(bind)?

asp.net - List<T> 的实现丢失了原始查询的顺序

entity-framework - 使用 SqlQuery 获取 IQueryable

c# - 将 EF CodeFirst 基类转换为继承类(使用 table-per-type)

c# - 如何更改启动画面图像的位置?

c# - List<Task> - 使用 C# Entity Framework 的 UPSERT 数据库记录

c# - 为什么两个进程比 2 个线程有优势?

entity-framework - EF代码优先的自定义初始化策略,该策略不会删除表以添加列

linq - ef cf linq 填充被忽略的属性

c# - 通过继承设计具有共享功能的静态类