涉及导航属性的查询的IQueryable.Count因为未加载而抛出

时间:2017-12-01 16:59:52

标签: c# entity-framework asp.net-core

如果在查询上使用.Count()方法,那么执行需要显式包含导航属性的过滤的查询将不会加载它们。在Where()子句中的过滤表达式运行时导致异常。

然而,将.Count()更改为.ToList()会使实体框架包含引用的导航属性并生成正确的结果

似乎Count()方法忽略导航属性,并且过滤表达式中的值为null

我的项目正在使用ASP Net Core 1.1和EntityFramework 1.1.4

示例代码

 public class ItemsService : IItemsService
{
    private readonly ApplicationDbContext dbContext;

    public ItemsService(ApplicationDbContext dbContext)
    {
        this.dbContext = dbContext;
    }

    public ISearchResult Search(ISearchOptions options)
    {
        var query = this.dbContext.Item
                                  .Include(i => i.Vehicle)
                                  .Include(x => x.Part).ThenInclude(p => p.PartCategory)
                                  .Where(i => i.IsDeleted == false);

        query = this.ApplyMakeFiltering(query, options.Make);
        query = this.ApplyModelFiltering(query, options.Model);

        var total = query.Count(); // Throws => NavigationProperty Vehicle is null
        var total2 = query.ToList().Count; // Works Correctly

        return new SearchResult(options, query, total);

    }

    private IQueryable<Item> ApplyMakeFiltering(IQueryable<Item> query, string make)
    {
        return this.Filter(
            query,
            make,                     // item.Vehicle is null for `Count()` but set correctly for `ToList()`
            item => this.StringMatches(item.Vehicle.CustomVehicleMakeName, make));
    }

    private IQueryable<Item> ApplyModelFiltering(IQueryable<Item> query, string model)
    {
        return this.Filter(
            query,
            model,
            item => this.StringMatches(item.Vehicle.CustomVehicleModelName, model));
    }

    private IQueryable<Item> Filter<T>(IQueryable<Item> query, T expected, Predicate<Item> matcher)
    {
        if (expected == null) return query;

        return query.Where(item => matcher(item));
    }

    private bool StringMatches(string a, string b)
    {
        if (String.IsNullOrEmpty(a)) return false;

        return a.Equals(b, StringComparison.OrdinalIgnoreCase);
    }
}

过滤后获得匹配结果计数的正确方法是什么?

0 个答案:

没有答案