gpt4 book ai didi

c# - LINQ 查询的 IReadOnlyCollection 部分

转载 作者:太空宇宙 更新时间:2023-11-03 16:05:00 27 4
gpt4 key购买 nike

我的模型(使用 Entity Framework 生成,请记住我已针对示例对其进行了简化)如下所示:

public class Person
{
public string Name { get; set; }
protected virtual ICollection<PersonHouseMapping> PersonHouseMappings { get; set; }

public virtual IReadOnlyCollection<House> GetHouses(Func<House, bool> where = null)
{
var houses = PersonHouseMappings.Select(x => x.House);

if (where != null)
houses = houses.Where(where);

return houses.ToList().AsReadOnly();
}

public void AddHouse(House house, DateTime movingDate)
{
PersonHouseMappings.Add(new PersonHouseMapping
{
Person = this,
House = house,
MovingDate = movingDate
});
}
}

public class House
{
public int Number { get; set; }
protected virtual ICollection<PersonHouseMapping> PersonHouseMappings { get; set; }
}

internal class PersonHouseMapping
{
public virtual Person Person { get; set; }
public virtual House House { get; set; }
public DateTime MovingDate { get; set; }
}

Person 和 Houses 之间存在 N:M 关系,由 PersonH​​ouseMapping 实体表示。通常 EF 会用导航属性来表示它,但是因为 PersonH​​ouseMapping 除了关系的每个实体部分的 PK 之外还有一个额外的字段,所以它不能这样做。

为了从我的库的用户那里抽象出 PersonH​​ouseMapping,因为它不像具有导航属性那样干净,我已经使 ICollection 受到保护,并通过可以在 Person 类中看到的方法公开查询/添加功能。我不希望用户修改返回的集合,因为他们可能认为向“GetHouses”的结果添加一个新的房子会被保存到数据库中,但事实并非如此。为了强制他们调用“AddHouse”,我将返回类型设置为 IReadOnlyCollection。

问题是,当我想为包含与其 Houses 相关的条件的 Person 构造查询时,LINQ 无法将表达式转换为有效的 Linq to Entities 表达式。假设我们想查询所有拥有编号为 1 的房子的人:

dbContext.Persons.Where(p => p.GetHouses(h => h.Number == 1).Any()).ToList();

这行不通,并抛出异常:

LINQ to Entities does not recognize the method 'System.Collections.Generic.IReadOnlyCollection`1[Namespace.House] GetHouses(System.Func`2[Namespace.House,System.Boolean])' method, and this method cannot be translated into a store expression.

这是有道理的。但是我怎样才能在保留执行这些查询的能力的同时完成我想要的呢?是否有类似 IEnumerable 的东西不能实例化到列表中?

编辑: 我认为通过返回 IEnumerable 而不是 IReadOnlyCollection 查询会起作用(尽管它不能解决我的问题),但事实并非如此。为什么不能创建表达式?

编辑 2: 返回 IEnumerable 也不起作用的原因是问题不在于类型,问题在于在 LINQ 表达式中间进行方法调用。它需要直接转换为商店查询,因此没有方法调用:(

非常感谢

最佳答案

唯一的方法是公开映射集合:

public virtual ICollection<PersonHouseMapping> PersonHouseMappings { get; set; }

并重写查询:

dbContext.Persons.Where(p => p.PersonHouseMappings.Any(m => m.House.Number == 1)).ToList();

EF 无法解析您的方法并从中构建表达式树的一部分。
实际上,我在您的查询中看不到任何优点。

关于c# - LINQ 查询的 IReadOnlyCollection 部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19842600/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com