Impossibile eseguire il cast dell'oggetto di tipo 'System.Linq.Expressions.FieldExpression' per digitare 'System.Linq.Expressions.ParameterExpression

entity-framework entity-framework-core linq

Domanda

Sto usando Entity Framework rc1-final in ASP.NET5.

Ho la seguente tabella.

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 è collegato a Player che è collegato al SubGroup che è collegato al Group

Ho la seguente query 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();
    }

Funziona correttamente

Ogni commento cade in un periodo, quindi nel mio output devo includere il periodo, quindi aggiungo il .Include("Period")

quindi il mio codice è simile a questo

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();
    }

Tuttavia ora getta un'eccezione di runtime e mi dà:

"Impossibile eseguire il cast dell'oggetto di tipo 'System.Linq.Expressions.FieldExpression' per digitare 'System.Linq.Expressions.ParameterExpression'."

Ho letto su Github c'è un problema con OrderBy dato l'errore ma non sto nemmeno usando l'ordine.

C'è qualche soluzione che posso usare per risolvere questo problema?

Mi sembra di averlo ristretto grazie alla risposta fornita da @octavioccl.

Cambiando il mio codice a questo:

        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;

Tutte le combinazioni funzionano, tranne quando seleziono GroupId e mantengo gli altri null . Poiché il SubGroup funziona, posso solo dedurre che si tratta di un problema quando si utilizza una inclusione e si utilizza dove profondità della clausola 3 livelli.

Risposta popolare

Dovresti provare a chiamare il metodo Include nel DbSet cui vuoi caricare l'entità correlata:

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

E penso che la tua query sarebbe più semplice se usi le proprietà di navigazione invece dei join espliciti:

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();

Aggiornare

Prova a spostare le condizioni in cui controlli se i parametri sono null al di fuori della tua query.

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();


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché