FindAsync和Include LINQ语句

Dev*_*per 25 c# linq entity-framework-6

到目前为止,我所获得的代码运行良好

public async Task<ActionResult> Details(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            ItemDetailModel model = new ItemDetailModel();
            model.Item = await db.Items.FindAsync(id);
            if (model.Item == null)
            {
                return HttpNotFound();
            }           
            return View(model);
        }
Run Code Online (Sandbox Code Playgroud)

但是我想要包含1个表并且不能使用 FindAsync

public async Task<ActionResult> Details(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            ItemDetailModel model = new ItemDetailModel();
            model.Item = await db.Items.Include(i=>i.ItemVerifications).FindAsync(id);


            if (model.Item == null)
            {
                return HttpNotFound();
            }           

            return View(model);
        }
Run Code Online (Sandbox Code Playgroud)

所以我面临这个错误

严重级代码描述项目文件行抑制状态错误CS1061'IQueryable'不包含'FindAsync'的定义,并且没有扩展方法'FindAsync'可以找到接受类型'IQueryable'的第一个参数(你是否缺少using指令或装配参考?)

有任何线索如何修复它?

Iva*_*oev 52

最简单的是使用FirstOrDefaultAsyncSingleOrDefaultAsync代替:

model.Item = await db.Items.Include(i => i.ItemVerifications)
    .FirstOrDefaultAsync(i => i.Id == id.Value);
Run Code Online (Sandbox Code Playgroud)

你得到错误的原因是因为Find/ FindAsync方法被定义DbSet<T>,但结果IncludeIQueryable<T>.

另一种方法是合并FindAsync明确的负载:

model.Item = await db.Items.FindAsync(id);
if (model.Item == null)
{
    return HttpNotFound();
}
await db.Entry(model.Item).Collection(i => i.ItemVerifications).LoadAsync();    
Run Code Online (Sandbox Code Playgroud)

  • 使用了第二个选项。干杯 (2认同)
  • 考虑到 [Find 与 FirstOrDefault 哪个更快的争论](/sf/ask/982289661/),这似乎表明“Find”更快,这样做会对性能产生负面影响。 (2认同)

小智 7

如果您使用的是通用存储库并且在运行时不知道 PK,则此方法可以提供帮助:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我希望这会访问数据库 2 次,而不是在 DbSet 上使用 Include 时的一次。遗憾的是 FindAsync 没有提供直接包含其他字段的功能。 (2认同)