Solución:
Lo más simple es usar FirstOrDefaultAsync
o SingleOrDefaultAsync
en lugar de:
model.Item = await db.Items.Include(i => i.ItemVerifications)
.FirstOrDefaultAsync(i => i.Id == id.Value);
La razón por la que recibe el error es porque Find
/ FindAsync
los métodos están definidos para DbSet<T>
, pero el resultado de Include
es IQueryable<T>
.
Otra forma es combinar FindAsync
con carga explícita:
model.Item = await db.Items.FindAsync(id);
if (model.Item == null)
{
return HttpNotFound();
}
await db.Entry(model.Item).Collection(i => i.ItemVerifications).LoadAsync();
Si está utilizando un repositorio genérico y no conoce el PK en tiempo de ejecución, este enfoque puede ayudar:
public interface IGenericRepository<TEntity> where TEntity : class
{
Task<TEntity> Get(int id, string[] paths = null);
}
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
private readonly ApplicationDbContext _context;
private readonly DbSet<TEntity> _dbSet;
public GenericRepository(ApplicationDbContext context)
{
_context = context;
_dbSet = _context.Set<TEntity>();
}
public async Task<TEntity> Get(int id, string[] paths = null)
{
var model = await _dbSet.FindAsync(id);
foreach (var path in paths)
{
_context.Entry(model).Reference(path).Load();
}
return model;
}
}
Cuando programe utilizando principios sólidos y diseño de dominio, utilice genéricos. El patrón Repository usa una clase genérica. Paso un lambda express a la función GetObjectsQueryable. He configurado la carga diferida para que esté activada, usando el código primero en las barras de control. Sin embargo, me estoy alejando de la carga diferida e implemento una arquitectura de microservicio. La tabla de inclusión es una cadena y puede utilizar la función nameof (xxclass) para garantizar el nombre correcto. La función devuelve resultados IQueryable. Los métodos de la clase de repositorio pueden ser utilizados por su clase derivada para mejorar el método está protegido. Esta es una demostración de dotnet.core.
public class Repository
where T : class
{
public IQueryable<T> GetObjectsQueryable(Expression<Func<T, bool>> predicate, string includeTable="")
{
IQueryable<T> result = _dbContext.Set<T>().Where(predicate);
if (includeTable != "")
result = result.Include(includeTable);
return result;
}
}