Linq to Entity Group By error 无法翻译

Posted

技术标签:

【中文标题】Linq to Entity Group By error 无法翻译【英文标题】:Linq to Entity Group By error can't translate 【发布时间】:2021-11-06 13:02:03 【问题描述】:

我尝试做这个查询:

var query = from cont in _gpiContext.Contacto
                        join per in _gpiContext.Persona on cont.IdPersona equals per.IdPersona
                        where cont.IdCliente == idCliente
                        && cont.IdTipoContacto == tipoContacto.IdTipoContacto
                        group new  cont, per  by new  cont.IdCliente, cont.IdContacto, cont.IdPersona  into g
                        select new Representante
                        
                            IdContacto = g.Key.IdContacto,
                            IdCliente = g.Key.IdCliente,
                            IdPersona = g.Key.IdPersona,
                            Nombre = g.First().per.Nombre
                        ;
return await query.ToListAsync();

我已经尝试了所有方法,但无法找出问题所在,我有非常相似的查询并且它们确实完美无缺。我不想做客户评估。

但我得到以下错误:

"LINQ 表达式 'GroupByShaperExpression: KeySelector: new IdCliente = (Nullable)c.ID_CLIENTE, IdContacto = c.ID_CONTACTO, IdPersona = (Nullable)c.ID_PERSONA , ElementSelector:new con = EntityShaperExpression: 实体类型:联系人 值缓冲区表达式: ProjectionBindingExpression: con IsNullable: 假 , 每 = EntityShaperExpression: 实体类型:角色 值缓冲区表达式: ProjectionBindingExpression:每 IsNullable: 真 .Select(s => s.per.Nombre) .First()' 无法翻译。要么以可翻译的形式重写查询,要么显式切换到客户端评估 通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”的调用, 或“ToListAsync”。见https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。”

我的实体: 联系方式

// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

#nullable disable

namespace GpiWebApp.Data.Gpi

    [Table("CONTACTO")]
    public partial class Contacto
    
        [Key]
        [Column("ID_CONTACTO", TypeName = "numeric(10, 0)")]
        public decimal IdContacto  get; set; 
        [Column("ID_CLIENTE", TypeName = "numeric(10, 0)")]
        public decimal? IdCliente  get; set; 
        [Column("ID_TIPO_CONTACTO", TypeName = "numeric(10, 0)")]
        public decimal? IdTipoContacto  get; set; 
        [Column("ID_PERSONA", TypeName = "numeric(10, 0)")]
        public decimal? IdPersona  get; set; 

        [ForeignKey(nameof(IdCliente))]
        [InverseProperty(nameof(Cliente.Contacto))]
        public virtual Cliente IdClienteNavigation  get; set; 
        [ForeignKey(nameof(IdPersona))]
        [InverseProperty(nameof(Persona.Contacto))]
        public virtual Persona IdPersonaNavigation  get; set; 
        [ForeignKey(nameof(IdTipoContacto))]
        [InverseProperty(nameof(TipoContacto.Contacto))]
        public virtual TipoContacto IdTipoContactoNavigation  get; set; 
    

角色

// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using Microsoft.EntityFrameworkCore;
    
    #nullable disable
    
    namespace GpiWebApp.Data.Gpi
    
        [Table("PERSONA")]
        public partial class Persona
        
            public Persona()
            
                Cliente = new HashSet<Cliente>();
                Contacto = new HashSet<Contacto>();
                DireccionPersona = new HashSet<DireccionPersona>();
                EmailPersona = new HashSet<EmailPersona>();
                TelefonoPersona = new HashSet<TelefonoPersona>();
            
    
            [Key]
            [Column("ID_PERSONA", TypeName = "numeric(10, 0)")]
            public decimal IdPersona  get; set; 
            [Required]
            [Column("TIPO_ENTIDAD")]
            [StringLength(1)]
            public string TipoEntidad  get; set; 
            [Column("NOMBRE")]
            [StringLength(100)]
            public string Nombre  get; set; 
            [Column("PATERNO")]
            [StringLength(50)]
            public string Paterno  get; set; 
            [Column("MATERNO")]
            [StringLength(50)]
            public string Materno  get; set; 
            [Column("SEXO")]
            [StringLength(1)]
            public string Sexo  get; set; 
            [Column("FECHA_NACIMIENTO", TypeName = "datetime")]
            public DateTime? FechaNacimiento  get; set; 
            [Required]
            [Column("IDENTIFICADOR")]
            [StringLength(12)]
            public string Identificador  get; set; 
            [Required]
            [Column("TIPO_IDENTIFICADOR")]
            [StringLength(1)]
            public string TipoIdentificador  get; set; 
            [Column("COD_PAIS")]
            [StringLength(3)]
            public string CodPais  get; set; 
            [Column("ID_ESTADO_CIVIL", TypeName = "numeric(3, 0)")]
            public decimal? IdEstadoCivil  get; set; 
            [Column("PROFESION")]
            [StringLength(20)]
            public string Profesion  get; set; 
            [Column("TELEFONO")]
            [StringLength(50)]
            public string Telefono  get; set; 
            [Column("CELULAR")]
            [StringLength(50)]
            public string Celular  get; set; 
            [Column("EMAIL")]
            [StringLength(50)]
            public string Email  get; set; 
            [Column("EMPLEADOR")]
            [StringLength(50)]
            public string Empleador  get; set; 
            [Column("CARGO")]
            [StringLength(50)]
            public string Cargo  get; set; 
            [Column("FLG_MAYOR_EDAD")]
            [StringLength(1)]
            public string FlgMayorEdad  get; set; 
            [Column("ID_TIPO_ESTADO", TypeName = "numeric(4, 0)")]
            public decimal? IdTipoEstado  get; set; 
            [Column("COD_ESTADO")]
            [StringLength(3)]
            public string CodEstado  get; set; 
            [Column("GIRO")]
            [StringLength(100)]
            public string Giro  get; set; 
            [Column("ID_TIPO_SOCIEDAD", TypeName = "numeric(3, 0)")]
            public decimal? IdTipoSociedad  get; set; 
            [Column("DSC_DOCUMENTO")]
            [StringLength(20)]
            public string DscDocumento  get; set; 
            [Column("OBSERVACIONES")]
            [StringLength(150)]
            public string Observaciones  get; set; 
            [Column("COPIA_ESCRITURA")]
            [StringLength(1)]
            public string CopiaEscritura  get; set; 
            [Column("FECHA_FORMACION", TypeName = "datetime")]
            public DateTime? FechaFormacion  get; set; 
            [Column("LUGAR")]
            [StringLength(80)]
            public string Lugar  get; set; 
            [Column("NOTARIA")]
            [StringLength(100)]
            public string Notaria  get; set; 
            [Column("REGISTRO")]
            [StringLength(100)]
            public string Registro  get; set; 
            [Column("NUMERO")]
            [StringLength(100)]
            public string Numero  get; set; 
            [Column("ANO")]
            [StringLength(100)]
            public string Ano  get; set; 
            [Column("ANTECEDENTES")]
            [StringLength(1)]
            public string Antecedentes  get; set; 
            [Column("SITIOWEB")]
            [StringLength(50)]
            public string Sitioweb  get; set; 
    
            [ForeignKey(nameof(CodPais))]
            [InverseProperty(nameof(Pais.Persona))]
            public virtual Pais CodPaisNavigation  get; set; 
            [ForeignKey(nameof(IdEstadoCivil))]
            [InverseProperty(nameof(EstadoCivil.Persona))]
            public virtual EstadoCivil IdEstadoCivilNavigation  get; set; 
            [ForeignKey(nameof(IdTipoSociedad))]
            [InverseProperty(nameof(TipoSociedad.Persona))]
            public virtual TipoSociedad IdTipoSociedadNavigation  get; set; 
            [InverseProperty("IdPersonaNavigation")]
            public virtual ICollection<Cliente> Cliente  get; set; 
            [InverseProperty("IdPersonaNavigation")]
            public virtual ICollection<Contacto> Contacto  get; set; 
            [InverseProperty("IdPersonaNavigation")]
            public virtual ICollection<DireccionPersona> DireccionPersona  get; set; 
            [InverseProperty("IdPersonaNavigation")]
            public virtual ICollection<EmailPersona> EmailPersona  get; set; 
            [InverseProperty("IdPersonaNavigation")]
            public virtual ICollection<TelefonoPersona> TelefonoPersona  get; set; 
        
    

感谢您的建议!

【问题讨论】:

我想知道它是从哪里来的tipoContacto.IdTipoContacto? 【参考方案1】:

为什么不试试这个

....
group new  cont, per  by new  cont.IdCliente, cont.IdContacto, cont.IdPersona, per.Nombre  into g
  select new Representante
    
     IdContacto = g.Key.IdContacto,
       IdCliente = g.Key.IdCliente,
       IdPersona = g.Key.IdPersona,
       Nombre = g.Key.Nombre
      ;

【讨论】:

他们为什么不试试呢?嗯,这是一个完全不同的分组。 OP 不想按Nombre 分组。又是一个冲动的答案,你过早地假设 OP 会像那样改变他们的要求。当然,这里唯一正确的答案是 EF 不支持它,他们必须找到解决方法。【参考方案2】:

Serge's answer 应该适用于这种特殊情况,但我想在您尝试在 LINQ 中使用分组做更复杂的事情之前,我会添加一些上下文。

查看 EFCore 文档中的 Complex query operators 部分。特别有趣的是他们说的部分:

由于没有数据库结构可以表示 IGrouping,因此 GroupBy 运算符在大多数情况下没有翻译。

这是有道理的,因为如果您用 SQL 术语来思考,那么您可以对 GROUP BY 进行的聚合很少,例如总和、计数、平均值、最小值、最大值;但是没有 FIRST 或 LAST(除非您进入分区和排名,这类似于分组,但实际上并非如此)。

所以,长话短说,您的查询实际上是有效的 LINQ。如果您尝试将其应用于List&lt;&gt;,它将起作用。但它永远无法翻译成服务器端的 SQL。

【讨论】:

以上是关于Linq to Entity Group By error 无法翻译的主要内容,如果未能解决你的问题,请参考以下文章

如何在 LINQ 中将 Group By 与 Task<IEnumerable<Entity>> 一起使用

LINQ to SQL 实现 GROUP BY聚合ORDER BY

C# Linq to SQL — Group by

Linq to Entities Group By 有一些没有元素的组

LINQ to SQL语句之Group By/Having

Linq to Entities基础之需要熟知14个linq关键字(from,where,select,group,let,on,by...)