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