【问题标题】:Only initializers, entity members, and entity navigation properties are supported仅支持初始化器、实体成员和实体导航属性
【发布时间】:2011-08-02 22:56:58
【问题描述】:

我遇到了这个异常:

LINQ to Entities 不支持指定的类型成员“付费”。 只有初始化器、实体成员和实体导航属性 支持。

    public ActionResult Index()
    {
        var debts = storeDB.Orders
            .Where(o => o.Paid == false)
            .OrderByDescending(o => o.DateCreated);

        return View(debts);
    }

我的模型课

public partial class Order
{
    public bool Paid {
        get {
            return TotalPaid >= Total;
        }
    }

    public decimal TotalPaid {
        get {
            return Payments.Sum(p => p.Amount);
        }
    }

Payments 是一个包含字段金额的相关表,如果我删除显示有关付款的正确信息的 Where 子句,则查询有效,是否知道代码有什么问题?

已解决,如建议的答案:

    public ActionResult Index()
    {
        var debts = storeDB.Orders
            .OrderByDescending(o => o.DateCreated)
            .ToList()
            .Where(o => o.Paid == false);

        return View(debts);
    }

【问题讨论】:

  • 简单回答:不能在 linq-to-entities 查询中使用未映射的属性!只有映射的属性被转换为 SQL。

标签: linq entity-framework


【解决方案1】:

实体正在尝试将您的付费属性转换为 SQL,但不能,因为它不是表架构的一部分。

你可以做的是让实体查询没有付费过滤器的表,然后过滤掉非付费的。

public ActionResult Index()
{
    var debts = storeDB.Orders
        //.Where(o => o.Paid == false)
        .OrderByDescending(o => o.DateCreated);

    debts = debts.Where(o => o.Paid == false);

    return View(debts);
}

当然,这意味着您将所有数据带回 Web 服务器并过滤其中的数据。如果要在数据库服务器上进行过滤,可以在表上创建计算列或使用存储过程。

【讨论】:

    【解决方案2】:

    只需要解决一个类似的问题。 上述解决方案需要在内存中处理,这是一种不好的做法(延迟加载)。

    我的解决方案是编写一个返回谓词的助手:

    public static class Extensions
    {
        public static Expression<Func<Order, bool>> IsPaid()
        {
            return order => order.Payments.Sum(p => p.Amount) >= order.Total;
        }
    }
    

    您可以将 linq 语句重写为:

    var debts = storeDB.Orders
                        .Where(Extensions.IsPaid())
                        .OrderByDescending(o => o.DateCreated);
    

    当您想重用计算逻辑 (DRY) 时,这很方便。 缺点是逻辑不在您的域模型中。

    【讨论】:

    • 有许多库试图使这种方法更加“内置”,请参阅:stackoverflow.com/a/27383641/470183。 Linq-to-entities 仅限于使用“规范函数”的表达式 - 可以转换为 SQL。 C# 6 引入了“表达式体函数”,但这些不是真正的 lambda(请参阅:stackoverflow.com/a/28411444/470183)。在框架中有这个还是很好的,因此 WIBNI data.uservoice.com/forums/…
    • 感谢Expression&lt;Func&lt;xx,yy&gt;&gt; 这个简单而简洁的例子。我以前也理解过,但现在看起来很明显。
    【解决方案3】:

    此问题也可能来自在您的 DB 模型和视图模型中具有相同名称的 [NotMapped] 属性。

    AutoMapper 在投影期间尝试从数据库中选择它;并且 NotMapped 属性显然在数据库中不存在。

    解决方法是Ignore从DB Model映射到View Model时AutoMapper配置中的属性。

    1. 在您的数据库模型中查找名称为 Foo 的 [NotMapped] 属性。
    2. 在您的视图模型中查找具有相同名称 Foo 的属性。
    3. 如果是这种情况,请更改您的 AutoMapper 配置。加.ForMember(a =&gt; a.Foo, b =&gt; b.Ignore());

    【讨论】:

    • Dang AutoMapper Projection 也抓住了我,谢谢你的回答!
    【解决方案4】:

    Linq 将语句转换为 SQL 语句并执行到 数据库。

    现在,这种转换只发生在实体成员、初始化器和实体导航属性中。 所以要实现函数或获取属性的比较,我们需要先将它们转换成内存列表,然后应用函数来检索数据。

    因此总体而言,

    var debts = storeDB.Orders.toList()
            .Where(o => o.Paid == false)
            .OrderByDescending(o => o.DateCreated);
    

    【讨论】:

    • 我建议让某人在订单上创建一个 toList() 是危险的,因为这意味着检索整个列表
    • 这对我有好处,因为我有问题的属性在 Sum Linq 函数中,而不是在 Where 子句中。因此,我没有获得不必要的数据,并且在检索到的数据上,我正在执行正在处理列表的 Linq Sum 函数。谢谢!起初看起来很糟糕的东西在某些情况下可能非常有用!
    【解决方案5】:

    另一个可能的原因是您的财产使用的是IEnumerable,而不是ICollection

    所以而不是:

    public class This
    {
        public long Id { get; set; }
        //...
        public virtual IEnumerable<That> Thats { get; set; }
    }
    

    这样做:

    public class This
    {
        public long Id { get; set; }
        //...
        public virtual ICollection<That> Thats { get; set; }
    }
    

    而且你是个笨拙的多莉……愚蠢的事情浪费了 2 个小时。

    【讨论】:

      【解决方案6】:

      如果您使用 EntityFramework 类型不支持,例如 unsigned int,也会发生这种情况。

      这是我遇到此类错误的情况。

      查看有关支持类型的更多信息: https://msdn.microsoft.com/en-us/library/ee382832(v=vs.100).aspx

      GFoley83 解释了这种情况有一些解决方法: How to use unsigned int / long types with Entity Framework?

      【讨论】:

      • 这个链接节省了不少时间!非常感谢!
      【解决方案7】:

      我遇到了这个问题,因为有一个只有 get without set 属性的成员变量

      这意味着它的auto calculated 和not stored 作为the table 中的一列

      因此它的not exist 在table schema 中

      所以make sure 任何成员变量not auto calculated 到have 一个getter 和setter 属性

      【讨论】:

        【解决方案8】:

        您的 edmx 和上下文模型有一些新添加到 db 中的不同属性。

        更新您的 EDMX 正确刷新它构建您的项目并再次运行。

        它会解决你的问题。

        问候, 加内什尼卡姆

        【讨论】:

          猜你喜欢
          • 2011-10-28
          • 1970-01-01
          • 1970-01-01
          • 2020-08-15
          • 2023-03-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多