0

我对 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);
    }
4

1 回答 1

0

如果你使用

HasRequired(p => p.MediaItem).WithMany();

你应该显示外键属性:

HasRequired(p => p.MediaItem).WithMany().HasForeignKey(p=>p.MediaItemId);

在 HasRequired(p => p.MediaItem).WithOptional(); 您还应该显示外键,但在这种情况下,您可以使用ForeignKeyAttribute, 或 method Map

于 2014-11-26T22:19:11.830 回答