【问题标题】:Calculated readonly Member as Calculated Column计算的只读成员作为计算列
【发布时间】:2020-10-20 10:18:48
【问题描述】:

我有以下课程,并希望能够使用这样的 Linq 查询dbContext.Example.Where(e=> e.IsBetween); 来查询它

public class Example {
  public DateTime Start {get; set;}
  public DateTime End {get; set;}
  public bool IsBetween => DateTime.Now >= Start && DateTime.Now <= End ;
}

但是,这会在运行时导致“无法翻译 LINQ 表达式 [...]。要么重写 [...] 要么切换到客户端评估”错误。

我有什么方法可以将只读属性IsBetween 链接到数据库中的计算列?

【问题讨论】:

  • 我已经在 asp.net core 3.1 List&lt;Example&gt; ls = new List&lt;Example&gt;(); ls.Where(x =&gt; x.IsBetween); 中尝试过它没有给我任何编译错误
  • 它不会抛出编译但运行时错误,应该指定,对不起!
  • @viveknuna 您尝试的只是 LINQ-to-Objects,而不是实体框架。除了反编译代码之外,没有办法将任意函数转换为 SQL。当您使用 LINQ 编写 EF 查询时,您使用 表达式,而不是 lambda 或函数
  • @Torui 您尝试的操作是不可能的——无法将函数转换为 SQL。 LINQ to EF 或 NHibernate 与 expressions 一起工作,如果可能的话,这些表达式会被翻译成 SQL。该错误清楚地表明您无法将该函数转换为 SQL

标签: c# linq linq-to-sql entity-framework-core ef-core-3.1


【解决方案1】:

错误表明 EF 无法将您的自定义方法(属性 getter)转换为 SQL。如果您有/想要将IsBetween 映射到数据库中的计算列,您应该这样做accordingly。像这样的东西(没有检查 SQL 的有效性):

public class Example {
  public DateTime Start {get; set;}
  public DateTime End {get; set;}
  public bool IsBetween {get; set;} ;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // your setup ...
    modelBuilder.Entity<Example>()
        .Property(p => p.IsBetween)
        .HasComputedColumnSql("getdate() >= Start AND getdate() <= END");
}

如果您希望IsBetween 仅存在于代码中,您将需要使用expression trees,或者例如:

public class Example {
  public DateTime Start {get; set;}
  public DateTime End {get; set;}
  public bool IsBetween => _func(this) ; 
  public static readonly Expression<Func<Example, bool>> IsBetweenExpr = e => 
      DateTime.Now >= e.Start && DateTime.Now <= e.End;
  private static readonly Func<Example, bool> _func = _expr.Compile();
}

dbContext.Example.Where(Example.IsBetweenExpr) ....;

【讨论】:

  • 这会引发 InvalidOperationException,因为 IsBetween 作为计算属性,缺少支持字段
  • 我相信你会得到以下异常。 > 实体类型“示例”需要定义主键。如果您 > 打算使用无密钥实体类型调用“HasNoKey()”。
  • @Torui,是的,请参阅更新后的帖子,显然您应该将 IsBetween 更改为自动实现的属性。
  • @viveknuna 我们可以放心地假设 OP 发布了一个最小示例,而不是整个班级。该最小示例是否具有键a)与计算的属性无关,并且b)OP已经遇到了这样的异常。所以Example 要么有钥匙,要么已经标记为无钥匙
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多