我对 EF 还很陌生,并且使用的是版本 6,并且陷入了一对一的关系。我的整体结构是我有一个 Gallery 对象,其中有一个 GalleryMediaItem 实体的 ICollection,每个 GalleryMediaItem 都有一个与之关联的 MediaItem 实体。请注意,GalleryMediaItem 实体要求基础 MediaItem 具有值,尽管 MediaItem 实体本身不知道 GalleryMediaItem,这是有意的,因为 MediaItem 实体可能与 GalleryMediaItem 之外的其他事物相关联。这是一个例子:
Gallery
---> ICollection<GalleryMediaItems>
---> [other properties]
---> MediaItem [has no knowledge of GalleryMediaItem]
我要做的是在我访问实例的MediaItem
属性时让延迟加载为 MediaItem 实体工作GalleryMediaItem
。我的数据库结构与上面的代码结构匹配(GalleryMediaItem 有 GalleryId 和 MediaItemId,但 MediaItem 没有 GalleryMediaItemId,也不应该)并且返回的对象始终为 null。奇怪的是MediaItemId
,我的GalleryMediaItem
实例上的属性已正确填充,但导航属性本身不起作用。我已经尝试了以下所有变体,但没有运气:
HasRequired(p => p.MediaItem).WithOptional();
HasRequired(p => p.MediaItem).WithMany();
等等。我尝试过的每个变体都没有出现任何错误,只是没有导航属性访问。
配置这个的正确方法是什么?哪里GalleryMediaItem
可以填写MediaItem
子实体,但MediaItem
它本身(通过 POCO 和数据库)不知道父所有者?
编辑
其中一条评论要求我展示用于检索单个项目的代码。我有一个通用框架位于我的 DbContext 实例之上,但在它下面是获取单个Gallery
实体的方法:
/// <summary>
/// Retrieves an entity based on the Id parameter.
/// </summary>
/// <typeparam name="E">The type of BaseEntity being retrieved.</typeparam>
/// <param name="Id">The Id to retrieve.</param>
/// <returns>A BaseEntity of type E if a match is found, otherwise null.</returns>
public virtual E GetById<E>(long Id)
where E : BaseEntity
{
var whereClause = DataUtilities.BuildOrExpressionTree<E, long>(new long[] { Id }, entity => entity.Id);
IQueryable<E> entities = this.GetTable<E>().Where(whereClause);
if (entities.Count() == 1)
return entities.First();
else
return null;
}
上面的BaseEntity
泛型只是一个超级基本的 POCO,上面有 Id、CreateDate、MaintDate 等内容。我的 POCO 类中没有一个使用属性来表示它们对应的 DB 值,一切都是通过流体 EF API 完成的。Gallery
直接继承BaseEntity
,所以这个泛型函数符合预期。
该DataUtilities.BuildOrExpressionTree
函数如下所示:
public static Expression<Func<TValue, bool>> BuildOrExpressionTree<TValue, TCompareAgainst>(IEnumerable<TCompareAgainst> list, Expression<Func<TValue, TCompareAgainst>> convertBetweenTypes)
{
ParameterExpression inputParam = convertBetweenTypes.Parameters[0];
var binaryExpressionTree = BuildBinaryOrTree(list.GetEnumerator(), convertBetweenTypes.Body, null);
return Expression.Lambda<Func<TValue, bool>>(binaryExpressionTree, new [] { inputParam });
}
private static Expression BuildBinaryOrTree<T>(IEnumerator<T> itemEnumerator, Expression expressionToCompareTo, Expression expression)
{
if (itemEnumerator.MoveNext() == false)
return expression;
ConstantExpression constant = Expression.Constant(itemEnumerator.Current, typeof(T));
BinaryExpression comparison = Expression.Equal(expressionToCompareTo, constant);
BinaryExpression newExpression;
if (expression == null)
newExpression = comparison;
else
newExpression = Expression.OrElse(expression, comparison);
return BuildBinaryOrTree(itemEnumerator, expressionToCompareTo, newExpression);
}