1

我有以下实体类:

using System;
using System.Collections.Generic;
using Facebook.Business.Domain.Accounts;

namespace Business.Domain.Posts
{
    /// <summary>
    /// This class defines a post.
    /// </summary>
    public class Post : Entity<Post>
    {
        #region Fields

        private UserAccount _author;
        private UserAccount _owner;
        private DateTime _date;
        private string _text;
        private IList<Comment> _comments; 

        #endregion

        #region Ctors

        protected Post()
        {
        }

        public Post(UserAccount author,
                    UserAccount owner,
                    DateTime date,
                    string text)
        {
            _author = author;
            _owner = owner;
            _date = date;
            _text = text;
            _comments = new List<Comment>();
        }

        #endregion

        /// <summary>
        /// Gets or sets the account that writes and sends the current post.
        /// </summary>
        public virtual UserAccount Author
        {
            get { return _author; }
            protected set { _author = value; }
        }

        /// <summary>
        /// Gets or sets the datetime of the current post.
        /// </summary>
        public virtual DateTime Date
        {
            get { return _date; }
            protected set { _date = value; }
        }

        /// <summary>
        /// Gets or sets the text of the current post.
        /// </summary>
        public virtual string Text
        {
            get { return _text; }
            protected set { _text = value; }
        }

        /// <summary>
        /// Gets or sets the user that receives the current post.
        /// </summary>
        public virtual UserAccount Owner
        {
            get { return _owner; }
            protected set { _owner = value; }
        }

        /// <summary>
        /// Gets or sets the comments for the current post.
        /// </summary>
        public virtual IList<Comment> Comments
        {
            get { return _comments; }
            protected set { _comments = value; }
        }

        public void Add(Comment comment)
        {
            _comments.Add(comment);
        }

        #region Implementation of ICommentable

        IEnumerable<Comment> ICommentable.Comments { get { return Comments; } }

        #endregion
    }
}

UserAccount 类对 Post 类一无所知,UserAccount 也是一个实体。

那么我需要在各自的存储库类中实现这个方法:

/// <summary>
/// Retrieve the posts that were posted by a given account: <paramrefname="author"/>
/// </summary>
/// <param name="author">An account.</param>
/// <returns>The posts that were posted by <paramref name="author"/></returns>
public IQueryable<Post> FindPostsFrom(UserAccount author)
{
    ContractUtil.NotNull(author);

    return Set.Where(post => post.Author.Equals(author));
}

但是当我运行测试时,我得到以下错误:

System.NotSupportedException:无法创建类型为“Facebook.Business.Domain.Accounts.UserAccount”的常量值。此上下文仅支持原始类型或枚举类型。

...和堆栈...

在 System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq) 在 System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 在 System.Data.Objects.ELinq.ExpressionConverter.EqualsTranslator。 TypedTranslate(ExpressionConverter parent, BinaryExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input) at System.Data.Objects。 ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, ref DbExpression source, ref DbExpressionBinding sourceBinding, ref DbExpression lambda) 在 System.Data.Objects.ELinq。ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq ) 在 System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 在 System.Data 的 System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)。 Objects.ELinq.ExpressionConverter.Convert() 在 System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable在 System.Data.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 在 System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 在 System.Data.Translate(ExpressionConverter parent, MethodCallExpression call)。 Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 在 System.Data.Objects.ELinq.ExpressionConverter。在 System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan (Nullable) 的 Convert()在 System.Data.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 在 System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 在 System.Data.Translate(ExpressionConverter parent, MethodCallExpression call)。 Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 在 System.Data.Objects.ELinq.ExpressionConverter。在 System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan (Nullable) 的 Convert()ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call ) 在 System.Data.Objects.ELinq.ExpressionConverter.Convert() 在 System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable) 在 System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call ) 在 System.Data.Objects.ELinq.ExpressionConverter.Convert() 在 System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable) 在 System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 在 System.Data.Objects.ELinq.ExpressionConverter。在 System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan (Nullable) 的 Convert()Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 在 System.Data.Objects.ELinq.ExpressionConverter。在 System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan (Nullable) 的 Convert()1 forMergeOption) at System.Data.Objects.ObjectQuery1.GetResults(Nullable 1 forMergeOption) at System.Data.Objects.ObjectQuery1.System.Collections.Generic.IEnumerable.GetEnumerator() at System.Linq.Enumerable.First(IEnumerable 1 source) at System.Linq.Queryable.First(IQueryable1 source) at Data.EntityFramework.Tests.PostRepositoryTests.FindPostsFrom_FindingAPostGivenAnAuthor_ShouldRetrieveIt() 在 PostRepositoryTests.cs:第 136 行

到目前为止,谁能解释一下这里发生了什么?似乎是我不应该使用导航属性来查询。

谁能给我一个替代解决方案?

提前致谢。

4

2 回答 2

1

在实体框架中,查询应始终在谓词中使用原始属性。所以你可以做

Set.Where(post => post.Author.Id == author.Id);

或者(正如 dutzu 建议的那样)暴露AuthorIdPost. 如果你这样做,你必须告诉 EFAuthorId并且Author它们都是同一个外键的一部分。这取决于您使用的 API(ObjectContext 或 DbContext)如何做到这一点。

EF 如此严格的一个原因(可能还有更多)是它不能对值类型或类的相等性做出任何假设。由于 EF 允许使用 POCO,Equals()否则==操作员将不会自动评估键值的相等性。POCO 必须明确实施IEquatable以确保密钥平等。另一方面,原始值的相等性总是被定义的。

于 2012-12-13T21:48:59.250 回答
1

因为它们是相关实体并且关系是一对多的(一个作者有很多帖子),这意味着每个帖子都有一个保留 authorId 值的字段。

您可以重写查询以搜索 post.authorId = author.Id 的帖子。

于 2012-12-13T14:00:00.233 回答