Entity Framework 表达式到 SQL 翻译

Entity Framework expression to SQL translation

看看这个IQueryable:

var query = from e in db.EntityA
            select new MyViewModel 
                       {
                           field1: e.field1,
                           field2: e.field2,
                           field3: (e.field4 == 4 ? "four" : e.field4 == 3 : "three":....)
                       }

我希望在 SQL 中进行 field3 计算,因为我可能会在此字段上进行筛选或排序。

在这一步,它工作正常,但代码很难看。

这是我想要做的:

public String SomeFunction(EntityA e)
{
    if (e.field4 == 4)
    {
       return "four";
    }
    ...
}

var query = from e in db.EntityA
            select new MyViewModel 
                       {
                           field1: e.field1,
                           field2: e.field2,
                           field3: SomeFunction(e)
                       }

它不起作用,因为 EF 无法将我的函数转换为 SQL 表达式。

我的问题是:我怎样才能帮助 EF 做到这一点?

我需要在很多查询中使用这个表达式。所以我试过这个:

public String SomeFunction(EntityA e)
{
    return (e.field4 == 4 ? "four" : e.field4 == 3 : "three":.... );
}

我不明白为什么它不起作用,因为它是完全相同的表达式!

其他问题:有没有办法让我创建 EF“附加组件”?

非常感谢您的帮助

您可以创建一个函数来包含 returns 转换表达式的丑陋代码:

public Expression<Func<EntityA, MyViewModel>> ConvertEntityA()
{
  e => new MyViewModel
  {
    field1: e.field1,
    field2: e.field2,
    field3:
      e.field4==4 ? "four" :
      e.field4==3 ? "three" :
      ...
  };
}

  var query = db.EntityA.Select(ConvertEntityA());

没有第三方扩展,你无法优雅地做到这一点。我建议 LINQKit 完成这样的任务

只需配置DbContextOptions:

builder
    .UseSqlServer(connectionString)
    .WithExpressionExpanding(); // enabling LINQKit extension

编写辅助函数:

public static class MyExensions
{
    [Expandable(nameof(SomeFunctionImpl))]
    public static string SomeFunction(int value)
        => throw new InvalidOperationException();

    private static Expression<Func<int, string>> SomeFunctionImpl()
    {
        return value => 
            value == 4 ? "four" : 
            value == 3 ? "three" : .... ;
    }
}

以及 LINQ 查询中的用法:

var query = 
    from e in db.EntityA
    select new MyViewModel 
    {
        field1 = e.field1,
        field2 = e.field2,
        field3 = MyExensions.SomeFunction(e.field4)
    };

也许向 table 添加一个计算属性?如果您希望在数据库中完成计算,并且您可能希望将结果用作过滤器,这会使一切变得非常简单。