Así que aquí está el trato: actualmente estoy usando EF Core 3.1 y digamos que tengo una entidad:
public class Entity
{
public int Id { get; set; }
public int AnotherEntityId { get; set; }
public virtual AnotherEntity AnotherEntity { get; set; }
}
Cuando DbSet<Entity> Entities
accedo de la manera normal, incluyo AnotherEntity como:
_context.Entities.Include(e => e.AnotherEntity)
Y esto funciona. ¿Por qué no, verdad? Entonces voy con:
_context.Entities.FromSqlRaw("SELECT * FROM Entities").Include(e => e.AnotherEntity)
Y esto también funciona. Ambos me devuelven la misma colección de objetos unidos con AnotherEntity. Luego uso un procedimiento almacenado que consiste en la misma consulta SELECT * FROM Entities
llamada spGetEntities:
_context.Entities.FromSqlRaw("spGetEntities")
¿adivina qué? Esto tambien funciona. Me da el mismo resultado pero sin unirse a AnotherEntity, obviamente. Sin embargo, si trato de agregar Incluir como este:
_context.Entities.FromSqlRaw("spGetEntities").Include(e => e.AnotherEntity)
Estoy obteniendo:
FromSqlRaw o FromSqlInterpolated se llamó con SQL no composable y con una consulta que lo componía. Considere llamar
AsEnumerable
después del método FromSqlRaw o FromSqlInterpolated para realizar la composición en el lado del cliente.
Aunque la salida de _context.Entities.FromSqlRaw("SELECT * FROM Entities")
y _context.Entities.FromSqlRaw("spGetEntities")
es idéntica.
No pude encontrar una prueba de que puedo o no puedo hacer esto con EF Core 3.1, pero si alguien pudiera darme alguna pista de la posibilidad de este enfoque, sería bueno.
Además, si hay otra forma de obtener entidades unidas utilizando un procedimiento almacenado, probablemente lo acepte como la solución de mi problema.
Respuestas:
En breve, no puede hacer eso (al menos para SqlServer). La explicación está contenida en la documentación de EF Core - Consultas SQL sin procesar - Composición con LINQ :
Además, dado que
Include
/ThenInclude
require EF CoreIQueryable<>
,AsEnumerable
/AsAsyncEnumerable
etc. no es una opción. Realmente necesita SQL composable, por lo tanto, los procedimientos almacenados no son una opción.Sin embargo, en lugar de procedimientos almacenados, puede usar funciones con valores de tabla (TVF) o vistas de base de datos porque son componibles (
select * from TVF(params)
oselect * from db_view
).fuente
En mi caso, estaba convirtiendo EF de trabajo
FromSql()
con un código de procedimiento almacenado 2.1 a 3.1. Al igual que:¿Dónde
AccountSums
está un SP.Lo único que tenía que hacer era usar
FromSqlRaw()
y agregarIgnoreQueryFilters()
para que volviera a funcionar. Al igual que:Esto se menciona en los comentarios, pero me perdí eso al principio, así que incluyo esto aquí.
fuente