No se puede convertir el objeto de tipo 'System.Linq.Expressions.FieldExpression' para escribir 'System.Linq.Expressions.ParameterExpression

entity-framework entity-framework-core linq

Pregunta

Estoy utilizando Entity Framework rc1-final en ASP.NET5.

Tengo la siguiente tabla.

public class PlayerComment 
{
    [Key]
    public int Id { get; set; }

    public int? PeriodId { get; set; }

    [ForeignKey("PeriodId")]
    public Period Period { get; set; }

    public int? PlayerId { get; set; }
    [ForeignKey("PlayerId")]
    public Player Player { get; set; 
    public DateTime? CommentDate { get; set; }

    public string Comment { get; set; }

}

PlayerComment está vinculado a Player que está vinculado a SubGroup que está vinculado a Group

Tengo la siguiente consulta de LINQ

public async Task<IEnumerable<PlayerComment>>  SearchQueryable(int? groupId, int? subGroupId = null, int? playerId = null)
    {

        var table = (from pc in _db.PlayerComments
                     join p in _db.Players on pc.PlayerId equals p.Id
                     join sg in _db.SubGroups on p.SubGroupId equals sg.Id
                     where (sg.GroupId == groupId || groupId == null)
                         &&
                         (p.SubGroupId == subGroupId || subGroupId == null)
                           &&
                         (p.Id == playerId || playerId == null)
                     select pc);
        return table.ToListAsync();
    }

Esto funciona correctamente.

Cada comentario cae en un período, por lo que en mi salida necesito incluir el período, así que agrego el .Include("Period")

así mi código se ve así

public async Task<IEnumerable<PlayerComment>>  SearchQueryable(int? groupId, int? subGroupId = null, int? playerId = null)
    {

        var table = (from pc in _db.PlayerComments
                     join p in _db.Players on pc.PlayerId equals p.Id
                     join sg in _db.SubGroups on p.SubGroupId equals sg.Id
                     where (sg.GroupId == groupId || groupId == null)
                         &&
                         (p.SubGroupId == subGroupId || subGroupId == null)
                           &&
                         (p.Id == playerId || playerId == null)
                     select pc).Include(p => p.Period);
        return table.ToListAsync();
    }

Sin embargo ahora lanza una excepción de tiempo de ejecución y me da:

"No se puede convertir el objeto de tipo 'System.Linq.Expressions.FieldExpression' para escribir 'System.Linq.Expressions.ParameterExpression'".

Leí en github, hay un problema con OrderBy da el error, pero ni siquiera estoy usando order by.

¿Hay alguna solución que pueda usar para arreglar esto?

Parece que lo he reducido gracias a la respuesta proporcionada por @octavioccl.

Cambiando mi código a esto:

        var table = _db.PlayerComments.Include(q => q.Period)
                      .Include(sg => sg.Player.SubGroup);
        IQueryable<PlayerComment> tableFiltered;
        if (playerId != null)
        {
            tableFiltered = table.Where(p => p.Player.Id == playerId)
        }
        else
        {
            if (subGroupId != null)
            {
                tableFiltered = table.Where(p => p.Player.SubGroupId == subGroupId)
            }
            else
            {
                if (groupId != null)
                {
                    tableFiltered = table.Where(p => p.Player.SubGroup.GroupId == groupId)
                }
                else
                {
                    tableFiltered = table
                }
            }

        }
        return tableFiltered;

Todas las combinaciones funcionan, excepto cuando selecciono GroupId y mantengo los otros null . Dado que el SubGroup funciona, solo puedo deducir que es un problema cuando se usa una inclusión y se usa en los niveles de la cláusula 3.

Respuesta popular

Debería intentar llamar al método Include en el DbSet en el que desea cargar la entidad relacionada:

 var table = (from pc in _db.PlayerComments.Include(p => p.Period)
              //...

Y creo que su consulta sería más simple si usara propiedades de navegación en lugar de uniones explícitas:

var table =await _db.PlayerComments.Include(p => p.Period)
                                   .Include(p => p.Player.SubGroup.Group)
                                   .Where(pc=>  ( pc.Player.SubGroup.Group.GroupId == groupId || groupId == null) 
                                             && ( pc.Player.SubGroup.SubGroupId == subGroupId || subGroupId == null)
                                             && ( pc.Player.Id == playerId || playerId == null))
                                   .ToListAsync();

Actualizar

Intente mover las condiciones donde verifica si los parámetros son null fuera de su consulta.

bool groupIdIsNull=groupId == null;
bool subGroupIdIsNull=subGroupId == null;
bool playerIdIsNull= playerId==null;

var table =await _db.PlayerComments.Include(p => p.Period)
                                   .Include(p => p.Player.SubGroup.Group)
                                   .Where(pc=>  ( groupIdIsNull || pc.Player.SubGroup.Group.GroupId.Value == groupId.Value) 
                                             && ( subGroupIdIsNull || pc.Player.SubGroup.SubGroupId.Value == subGroupId.Value )
                                             && ( playerIdIsNull || pc.Player.Id.Value == playerId.Value))
                                   .ToListAsync();


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué