在包含的实体上使用Contains()

时间:2019-02-04 18:45:53

标签: c# asp.net-mvc razor asp.net-core

我有以下代码:

    Intent intent1 = new Intent(this, SettingsActivity.class);
    PendingIntent pi = PendingIntent.getActivity(this, 1,intent1, 0);

执行代码时出现此错误:

InvalidOperationException:属性表达式'x => {来自x.PdReferences中的PdReference y,其中[y] .ReferenceName.Contains(__ searchString_1)select [y]}'无效。该表达式应表示属性访问:“ t => t.MyProperty”。有关包含相关数据的更多信息,请参见http://go.microsoft.com/fwlink/?LinkID=746393

我想我必须以另一种方式在包含的属性上使用Contains()。我尝试了很多事情,但是似乎没有任何合理的代码起作用。

有人可以帮我吗?

非常感谢

我的域模型:

    public PaginatedList<PdModel> PdModel { get; set; }
    public async Task OnGetAsync(int id, int? pageIndex, string searchString)
    {
        IQueryable<PdModel> PdModelsQuer = _context.PdModel.Where(x => x.Id == id)
                                .Include(x => x.PdTables)
                                .Include(x => x.pdFolderTree)
                                .Include(x => x.PdReferences.Where(y=>y.ReferenceName.Contains(searchString)))
                                .Include(x => x.pdViews)
                                .Include(x => x.pdDomains)
                                .Include(x => x.PdModelSources)
                                .Include(x => x.pdModelExtendeds)
                                .Include(x => x.pdRules);






        PdModel = await PaginatedList<PdModel>.CreateAsync(PdModelsQuer, 1, 10);
    }

1 个答案:

答案 0 :(得分:2)

您无法过滤急切加载的关系。您收到的错误是由于需要向Include传递有效的属性表达式,而Where子句则不需要。

如果只想加载此特定关系的子集,则需要显式加载它。例如:

IQueryable<PdModel> PdModelsQuer = _context.PdModel.Where(x => x.Id == id)
                            .Include(x => x.PdTables)
                            .Include(x => x.pdFolderTree)
                            // remove this .Include(x => x.PdReferences.Where(y=>y.ReferenceName.Contains(searchString)))
                            .Include(x => x.pdViews)
                            .Include(x => x.pdDomains)
                            .Include(x => x.PdModelSources)
                            .Include(x => x.pdModelExtendeds)
                            .Include(x => x.pdRules);

foreach (var pdModel in PdModelsQuer)
{
    var pdReferences = await _context.Entry(pdModel).Collection(x => x.PdReferences).Query()
        .Where(x = x.ReferenceName.Contains(searchString)).ToListAsync();
}

如果不是很明显,则意味着发出N + 1个查询,其中N是您的PdModels的计数。换句话说,必须为每个实例分别获取过滤后的集合。

但是,基于id的查询,看来您应该只有一个匹配的PdModel。因此,您实际上不应该在这里使用Where。代替。只需添加所有包含,然后使用SingleOrDefaultAsync

var pdModel = await _context.PdModel
    .Include(x => x.PdTables)
    .Include(x => x.pdFolderTree)
    .Include(x => x.pdViews)
    .Include(x => x.pdDomains)
    .Include(x => x.PdModelSources)
    .Include(x => x.pdModelExtendeds)
    .Include(x => x.pdRules)
    .SingleOrDefaultAsync(x => x.Id == id);

然后,您可以仅获取该实例的PdReferences:

var pdReferences = await _context.Entry(pdModel).Collection(x => x.PdReferences).Query()
    .Where(x = x.ReferenceName.Contains(searchString)).ToListAsync();

重要的是要注意,它被存储在另一个变量中。将过滤后的集合直接设置为PdReferences属性可能会产生副作用,尤其是如果您最终尝试稍后保存该实体时,即从数据库中删除过滤后列表中没有的任何内容。在这种情况下,最好采用视图模型并相应地映射数据。