[英]EF Core 5 - LINQ cannot be translated
好吧,我知道這有很多問題,但我還沒有找到我的問題的答案。
我在實體類中有規則:
class 事件:
public virtual ICollection<Sessao> Sessao { get; set; }
public bool Ativo()
{
return DataPublicacao <= DateTime.Today
&& (!DataFim.HasValue || DataFim.Value >= DateTime.Today)
&& Sessao.Any(sessao => sessao.Ativa());
}
class Sessao:
public bool Ativa() => Status == StatusSessao.Ativa && (Recorencia && DataInicio <= DateTime.Today || (!Recorencia && DataInicio <= DateTime.Today && DataFim >= DateTime.Today));
//I had try to put DateTime.Today in a variable, but same exception
LINQ 代碼:
var cardsEventos = await Consulta //DbSet<Evento>
.Include(x => x.Sessao)
.Where(ev => ev.Ativo())
.Where(x => x.Destaque) //...
調用該方法時,它會拋出帶有該消息的異常:
System.InvalidOperationException: The LINQ expression 'DbSet<Evento>()
.Where(e => e.Ativo())' could not be translated.
但是,如果我將相同的規則直接放在 linq 上,它就可以工作。
軟件其他部分的所有規則都是相同的,所以我認為這些規則只有一個失敗點,我該怎么做?
我建議使用LINQKit 。 它需要配置DbContextOptions
:
builder
.UseSqlServer(connectionString) // or any other Database Provider
.WithExpressionExpanding(); // enabling LINQKit extension
按以下方式定義您的方法。 我們只需要他們的表達式樹:
class Evento
{
... // other properties
public virtual ICollection<Sessao> Sessao { get; set; }
[Expandable(nameof(ActivoImpl))]
public bool Ativo()
{
throw new InvalidOperationException("Server side only method");
}
// this method will be invoked by LINKQKit and LambdaExpression
// will be injected into final Expression Tree before passing to EF Core
private static Expression<Func<Evento, bool>> ActivoImpl()
{
// for instance methods `this` is represented as first lambda parameter
return evento => evento.DataPublicacao <= DateTime.Today
&& (!evento.DataFim.HasValue || evento.DataFim.Value >= DateTime.Today)
&& evento.Sessao.Any(sessao => sessao.Ativa());
}
}
class Sessao
{
... // other properties
[Expandable(nameof(ActivaImpl))]
public bool Ativa()
{
throw new InvalidOperationException("Server side only method");
}
private static Expression<Func<Sessao, bool>> ActivaImpl()
{
return sessao => sessao.Status == StatusSessao.Ativa
&& (sessao.Recorencia && sessao.DataInicio <= DateTime.Today
|| (!sessao.Recorencia && sessao.DataInicio <= DateTime.Today && sessao.DataFim >= DateTime.Today)
);
}
}
然后您的 LINQ 查詢應該可以在沒有任何更改的情況下工作:
var cardsEventos = await Consulta //DbSet<Evento>
.Include(x => x.Sessao)
.Where(ev => ev.Ativo())
.Where(x => x.Destaque)
您可能希望將代碼重寫為
LINQ 代碼:
var ativa = sessao.Ativa();
var cardsEventos = await Consulta //DbSet<Evento>
.Include(x => x.Sessao)
.Where(ev => DataPublicacao <= DateTime.Today
&& (!DataFim.HasValue || DataFim.Value >= DateTime.Today)
&& Sessao.Any(sessao => ativa))
.Where(x => x.Destaque)
只需替換所需的代碼以顯示需要進行的更改。 OP 可能需要根據需要重新調整變量和屬性。
Linq 到實體不允許方法,因為所有條件都需要映射到 SQL 等效項,對於 C# 方法沒有。
如果您在變量中獲取返回值並在查詢中使用這些變量,則會更容易。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.