实体框架 6 - 一到可选关系
本文关键字:关系 框架 实体 | 更新日期: 2023-09-27 18:32:04
我对 EF 相当陌生并使用版本 6,并且停留在一对一的关系上。我的整体结构是我有一个 Gallery 对象,它里面有一个 GalleryMediaItem 实体的 ICollection,每个 GalleryMediaItem 都有一个与之关联的 MediaItem 实体。请注意,GalleryMediaItem 实体要求基础 MediaItem 具有值,尽管 MediaItem 实体本身不知道 GalleryMediaItem,这是有意为之的,因为 MediaItem 实体可以绑定到 GalleryMediaItem 以外的其他内容。下面是一个示例:
Gallery
---> ICollection<GalleryMediaItems>
---> [other properties]
---> MediaItem [has no knowledge of GalleryMediaItem]
我正在尝试做的是在我从GalleryMediaItem
实例访问 MediaItem
属性时让延迟加载为 MediaItem 实体工作。我的数据库结构与上面的代码结构匹配(GalleryMediaItem 有一个 GalleryId 和一个 MediaItemId,但 MediaItem 没有 GalleryMediaItemId,也不应该),并且返回的对象始终为 null。这里的奇怪部分是我的GalleryMediaItem
实例上的MediaItemId
属性已正确填充,但导航属性本身不起作用。我已经尝试了以下每种变体,但没有运气:
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 类都没有使用其相应数据库值的属性,一切都通过流体 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);
}
如果你使用
HasRequired(p => p.MediaItem).WithMany();
您应该显示外键属性:
HasRequired(p => p.MediaItem).WithMany().HasForeignKey(p=>p.MediaItemId);
In HasRequired(p => p.MediaItem)。WithOptional();您还应该显示外键,但在这种情况下,您可以使用 ForeignKeyAttribute
或方法 Map
。