【问题标题】:Creating a property that LINQ to Entities can translate创建 LINQ to Entities 可以翻译的属性
【发布时间】:2012-05-09 02:15:41
【问题描述】:

我很好奇如何创建一个可由 LINQ 翻译的属性。下面是一个非常简单的例子。

我有一个表/类 Category,其中有一列 ParentId 链接到自身(因此一个类别可以有子类别)

EF 自动生成一个属性Category1,即父类。

为了清楚起见,我创建了另一个属性

public partial class Category
{
  public Category Parent
  {
    get { return Category1; }
  }
}

问题是,这行得通

var categs = ctx.Categories.Where(x => x.Category1 == null);

但这不起作用

var categs = ctx.Categories.Where(x => x.Parent == null);

LINQ to Entities 不支持指定的类型成员“父级”。仅支持初始化程序、实体成员和实体导航属性。

有没有什么方法可以在不执行 .ToList() 的情况下创建可翻译的属性(LINQ to SQL)?

编辑:我想避免接触 Model.edmx,因为数据库在开发过程中经常发生变化,而且 .edmx 经常需要重新创建

【问题讨论】:

  • 您需要创建一个从类别到父级的导航属性,如外键
  • 嗨冷告诉,对不起,我不确定你的意思。已经有外键(否则EF不会创建Category1)
  • 您是否真正查看过 Model.Designer.cs 和/或 Reflector 中的 Category1 以查看其定义中添加了哪些属性或其他工具?
  • 是的,但我不明白,我尝试复制它们但没有用

标签: c# .net entity-framework linq-to-entities


【解决方案1】:

如果您询问是否可以使用 getter/setter 中的任何 C# 代码创建一个属性,然后让标准 LINQ to Entities 理解它 - 那么不,它无法完成。 C# 比 SQL 更具表现力,期望 Entity Framework 充当通用的 C# 到 SQL 转换器是不合理的。

在很多情况下,您都可以解决此问题,请参阅 Using a partial class property inside LINQ statement 以获取示例。

更新

如果您告诉我们您想要实现的具体目标会有所帮助,但这里有一个示例:

public partial class Category
{
    public static Expression<Func<Category, bool>> ParentIsNullExpression
    {
        get 
        {
            return c => c.Category1 == null;
        }
    }
}

然后

var categs = ctx.Categories.Where(Category.ParentIsNullExpression);

可以对表达式进行各种操作,其中一些受 EF 支持,因此可以转换为 SQL。

【讨论】:

  • 不能用C#实现吗?但是 Model.Designer.cs 本身(EDMX 的 CS 文件)是 C#,不是吗?您是指从该链接返回表达式的属性吗?我去看看。
  • 是的,我指的是表达式属性。使它在 Model.Designer.cs 中工作的不是属性代码,而是您用来访问属性的表达式,例如c =&gt; c.Category。 EF 知道您需要 Category 属性并将其转换为 Category 列/表。
  • 抱歉,我从未使用过表达式属性。您是说表达式属性有可能被翻译成 SQL 吗?您可以用表达式属性替换我的问题中的 Parent 属性,以便 LINQ 可以翻译它吗?谢谢雅克
  • 非常有趣!谢谢Jacek的完整答案!这是 顺便说一句
【解决方案2】:

在您的实体数据模型设计器(.edmx 文件)中,您可以将 Category1 重命名为 Parent

【讨论】:

  • 这只是一个非常简单的例子。我在问如何编写属性,而不是重命名现有属性。还是谢谢。
【解决方案3】:

您有 4 个选项:

  1. 先使用代码
  2. 将其添加到 EDMX 设计器中
  3. 将您的属性添加到 EDMX 的 CSDL 部分,向 EDMX 的 SSDL 部分添加一列,然后在 EDMX 的映射部分中将它们相互映射。
  4. 使用 .ToList() 将查询带入内存,然后使用内部 LINQ 而不是 LINQ to Entities。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    相关资源
    最近更新 更多