gpt4 book ai didi

entity-framework - 当我在 EF4 代码中进行一对多映射时,是否可以隐藏我的 ICollection 字段?

转载 作者:行者123 更新时间:2023-12-04 15:48:39 25 4
gpt4 key购买 nike

我的具有一对多映射的域类通常采用以下形式(未经测试的代码):

public Customer Customer
{
// Public methods.

public Order AddOrder(Order order)
{
_orders.Add(order);
}

public Order GetOrder(long id)
{
return _orders.Where(x => x.Id).Single();
}

// etc.

// Private fields.

private ICollection<Order> _orders = new List<Order>();
}

EF4 code-only samples在处理一对多关系时,我见过公开的 ICollection。

有没有办法通过公开它们来保留和恢复我的收藏?如果不是这样,我的领域对象似乎将被设计为满足 ORM 的要求,这似乎与努力的精神背道而驰。公开 ICollection(使用它的 Add 等方法)似乎不是特别干净,也不是我的默认方法。

更新

找到 this post这表明五月份不可能。当然,微软的海报确实说他们正在“强烈考虑实现”它(我希望如此)而且我们已经过去了半年,所以也许已经取得了一些进展?

最佳答案

我发现无论做什么,EF 都需要 ICollection<T>公开。我认为这是因为从数据库加载对象时,映射会查找集合属性,获取集合然后调用 Add集合的方法来添加每个子对象。

我想确保添加是通过父对象上的方法完成的,因此创建了一个包装集合、捕获添加并将其定向到我首选的添加方法的解决方案。

扩展 List和其他集合类型是不可能的,因为 Add方法不是虚拟的。一种选择是扩展 Collection类并覆盖 InsertItem方法。

我只关注 Add , Remove , 和 Clear ICollection<T> 的功能接口(interface),因为那些是可以修改集合的接口(interface)。

首先,是我的基本集合包装器,它实现了 ICollection<T>界面
默认行为是正常集合的行为。但是,调用者可以指定一个替代 Add要调用的方法。此外,调用者可以强制 Add , Remove , Clear将选项设置为 null 不允许操作.这导致 NotSupportedException如果有人尝试使用该方法,则会被抛出。

抛出异常不如一开始就阻止访问。但是,应该对代码进行测试(单元测试),并且会很快发现异常并进行适当的代码更改。

public abstract class WrappedCollectionBase<T> : ICollection<T>
{

private ICollection<T> InnerCollection { get { return GetWrappedCollection(); } }

private Action<T> addItemFunction;
private Func<T, bool> removeItemFunction;
private Action clearFunction;


/// <summary>
/// Default behaviour is to be like a normal collection
/// </summary>
public WrappedCollectionBase()
{
this.addItemFunction = this.AddToInnerCollection;
this.removeItemFunction = this.RemoveFromInnerCollection;
this.clearFunction = this.ClearInnerCollection;
}

public WrappedCollectionBase(Action<T> addItemFunction, Func<T, bool> removeItemFunction, Action clearFunction) : this()
{
this.addItemFunction = addItemFunction;
this.removeItemFunction = removeItemFunction;
this.clearFunction = clearFunction;
}

protected abstract ICollection<T> GetWrappedCollection();

public void Add(T item)
{
if (this.addItemFunction != null)
{
this.addItemFunction(item);
}
else
{
throw new NotSupportedException("Direct addition to this collection is not permitted");
}
}

public void AddToInnerCollection(T item)
{
this.InnerCollection.Add(item);
}

public bool Remove(T item)
{
if (removeItemFunction != null)
{
return removeItemFunction(item);
}
else
{
throw new NotSupportedException("Direct removal from this collection is not permitted");
}
}

public bool RemoveFromInnerCollection(T item)
{
return this.InnerCollection.Remove(item);
}

public void Clear()
{
if (this.clearFunction != null)
{
this.clearFunction();
}
else
{
throw new NotSupportedException("Clearing of this collection is not permitted");
}
}

public void ClearInnerCollection()
{
this.InnerCollection.Clear();
}

public bool Contains(T item)
{
return InnerCollection.Contains(item);
}

public void CopyTo(T[] array, int arrayIndex)
{
InnerCollection.CopyTo(array, arrayIndex);
}

public int Count
{
get { return InnerCollection.Count; }
}

public bool IsReadOnly
{
get { return ((ICollection<T>)this.InnerCollection).IsReadOnly; }
}

public IEnumerator<T> GetEnumerator()
{
return InnerCollection.GetEnumerator();
}

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return InnerCollection.GetEnumerator();
}

}

鉴于该基类,我们可以通过两种方式使用它。示例是使用原始帖子对象。

1)创建特定类型的包装集合(例如, List)
公共(public)类 WrappedListCollection : WrappedCollectionBase, IList
{
私有(private)列表内部列表;
    public WrappedListCollection(Action<T> addItemFunction, Func<T, bool> removeItemFunction, Action clearFunction)
: base(addItemFunction, removeItemFunction, clearFunction)
{
this.innerList = new List<T>();
}

protected override ICollection<T> GetWrappedCollection()
{
return this.innerList;
}
<...snip....> // fill in implementation of IList if important or don't implement IList
}

然后可以使用它:
 public Customer Customer
{
public ICollection<Order> Orders {get { return _orders; } }
// Public methods.

public void AddOrder(Order order)
{
_orders.AddToInnerCollection(order);
}

// Private fields.

private WrappedListCollection<Order> _orders = new WrappedListCollection<Order>(this.AddOrder, null, null);
}

2)给一个集合使用
 public class WrappedCollection<T> : WrappedCollectionBase<T>
{
private ICollection<T> wrappedCollection;

public WrappedCollection(ICollection<T> collectionToWrap, Action<T> addItemFunction, Func<T, bool> removeItemFunction, Action clearFunction)
: base(addItemFunction, removeItemFunction, clearFunction)
{
this.wrappedCollection = collectionToWrap;
}

protected override ICollection<T> GetWrappedCollection()
{
return this.wrappedCollection;
}
}

可以按如下方式使用:

{
公共(public) ICollection 订单 {get { return _wrappedOrders; } }
//公共(public)方法。
 public void AddOrder(Order order)
{
_orders.Add(order);
}

// Private fields.
private ICollection<Order> _orders = new List<Order>();
private WrappedCollection<Order> _wrappedOrders = new WrappedCollection<Order>(_orders, this.AddOrder, null, null);
}

还有其他一些方法可以调用 WrappedCollection构造函数
例如,覆盖添加但保持删除和清除正常
private WrappedListCollection<Order> _orders = new WrappedListCollection(this.AddOrder,  (Order o) => _orders.RemoveFromInnerCollection(o), () => _orders.ClearInnerCollection());

我同意最好 EF 不要求公开收藏,但此解决方案允许我控制对收藏的修改。

对于阻止访问集合进行查询的问题,您可以使用上面的方法 2) 并设置 WrappedCollection GetEnumerator抛出 NotSupportedException 的方法.然后你的 GetOrder方法可以保持原样。然而,一种更简洁的方法可能是公开包装的集合。例如:
 public class WrappedCollection<T> : WrappedCollectionBase<T>
{
public ICollection<T> InnerCollection { get; private set; }

public WrappedCollection(ICollection<T> collectionToWrap, Action<T> addItemFunction, Func<T, bool> removeItemFunction, Action clearFunction)
: base(addItemFunction, removeItemFunction, clearFunction)
{
this.InnerCollection = collectionToWrap;
}


protected override ICollection<T> GetWrappedCollection()
{
return this.InnerCollection;
}
}

然后调用 GetOrder方法会变成
_orders.InnerCollection.Where(x => x.Id == id).Single();

关于entity-framework - 当我在 EF4 代码中进行一对多映射时,是否可以隐藏我的 ICollection<T> 字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4087225/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com