【发布时间】:2011-07-12 01:03:55
【问题描述】:
我在两个实体之间存在多对多关系 - Media 和 MediaCollection。我想检查某个媒体是否已存在于集合中。我可以这样做:
mediaCollection.Media.Any(m => m.id == mediaId)
但是,mediaCollection.Media 是一个 ICollection,所以在我看来,它必须从数据库中检索集合中的每个媒体才能进行此检查。由于一个集合中可能有许多媒体,这似乎非常低效。我在想我应该使用 IQueryable 的方法,但我看不到如何为多对多关系执行此操作。
如何在不检索整个集合的情况下检查关系是否存在?
编辑
我正在从我的数据库生成 EF 数据模型,然后使用内置的 VS POCO T4 模板来生成我的数据上下文和实体类。我认为问题在于生成的代码没有返回导航属性的 EntityCollection,而是返回 ObjectSet。 ObjectSet 实现了 IQueryable,但没有公开 CreateSourceQuery() 方法。
以下是上下文相关行的精简版本:
public partial class Entities : ObjectContext
{
public const string ConnectionString = "name=Entities";
public const string ContainerName = "Entities";
#region Constructors
public Entities()
: base(ConnectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
}
public Entities(string connectionString)
: base(connectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
}
public Entities(EntityConnection connection)
: base(connection, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
}
#endregion
#region ObjectSet Properties
public ObjectSet<MediaCollection> MediaCollections
{
get { return _mediaCollections ?? (_mediaCollections = CreateObjectSet<MediaCollection>("MediaCollections")); }
}
private ObjectSet<MediaCollection> _mediaCollections;
// snipped many more
#endregion
}
这里是 MediaCollection 实体类的精简版:
public partial class MediaCollection
{
#region Primitive Properties
// snipped
#endregion
#region Navigation Properties
public virtual ICollection<Medium> Media
{
get
{
if (_media == null)
{
var newCollection = new FixupCollection<Medium>();
newCollection.CollectionChanged += FixupMedia;
_media = newCollection;
}
return _media;
}
set
{
if (!ReferenceEquals(_media, value))
{
var previousValue = _media as FixupCollection<Medium>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupMedia;
}
_media = value;
var newValue = value as FixupCollection<Medium>;
if (newValue != null)
{
newValue.CollectionChanged += FixupMedia;
}
}
}
}
private ICollection<Medium> _media;
private void FixupMedia(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Medium item in e.NewItems)
{
if (!item.MediaCollections.Contains(this))
{
item.MediaCollections.Add(this);
}
}
}
if (e.OldItems != null)
{
foreach (Medium item in e.OldItems)
{
if (item.MediaCollections.Contains(this))
{
item.MediaCollections.Remove(this);
}
}
}
}
// snip
#endregion
}
最后,这是模板也生成的 FixupCollection:
public class FixupCollection<T> : ObservableCollection<T>
{
protected override void ClearItems()
{
new List<T>(this).ForEach(t => Remove(t));
}
protected override void InsertItem(int index, T item)
{
if (!this.Contains(item))
{
base.InsertItem(index, item);
}
}
}
【问题讨论】:
标签: entity-framework entity-framework-4.1