EF核心:通过未映射的样板属性进行过滤



我有一些实体类,它们包含一个未映射的整数属性,用于对由实体表示的数据进行分类。

public partial class HouseEntity
{
[NotMapped]
public int DataCategory { get => 5; }
// other mapped properties
// mapped bit property
public bool IsPublic { get; set; }
} 

我希望能够编写复杂的过滤语句,基于内存中的常量,也基于存储的值,如以下所示:

public IEnumerable<HouseEntity> GetHouses()
{
List<int> categoryPermissions = new List<int>() {1, 2, 3}; // usually obtained through service 

return context.HouseEntities
.Where(he => categoryPermissions.Contains(he.DataCategory) ||  he.IsPublic == true )
.ToList();
}

问题是上面的linq语句抛出了一个异常,因为它无法编译为sql。

是否有通过硬编码内存属性进行过滤的变通方法或任何其他方法?

由于是[NotMapped],因此无法对数据库执行查询。

但你可以在记忆中使用这样的小技巧:

public IEnumerable<HouseEntity> GetHouses()
{
List<int> categoryPermissions = new List<int>() {1, 2, 3}; // usually obtained through service 

// note the tolist here
return context.HouseEntities.ToList()
.Where(he => categoryPermissions.Contains(he.DataCategory) ||  he.IsPublic == true )
.ToList();
}

或者,您可以使用扩展方法来获得更流畅的语法,这也有助于提高性能:即:首先执行数据库索引部分,然后执行";ToList";然后是内存部分。尽管如此,通过链接查询来编写类似OR的表达式可能会很棘手。

如何使用不存在的列使用WHERE语句编写自己的SQL查询?你不能。

您可以做的是根据映射到列的属性进行筛选,然后在查询返回数据库结果后,根据未映射的属性进行过滤,因为到那时您将对存储在内存中的集合进行操作:

public IEnumerable<HouseEntity> GetHouses()
{
List<int> categoryPermissions = new List<int>() {1, 2, 3}; // usually obtained through service 

return context.HouseEntities
.Where(he => he.IsPublic == true)
.ToList()
.Where(he => categoryPermissions.Contains(he.DataCategory))
.ToList();
}

还要考虑返回HouseEntityIReadOnlyListList,因为这就是您最终返回的内容。


此外,您的查询可能无法工作,因为在列表上调用了Contains()。尝试使用IEnumerable或更新到EF Core 3.1有关该问题的更多信息:

  • EF Core 3 x。表达式中的Contains((,其中x是ICollection
  • https://github.com/dotnet/efcore/pull/17599

我确认我无法使用实体框架核心3.1.1 运行上面的代码

问题是我不能把EF变成";展望未来";并说服它从属性中获取值,这可能是因为它需要一个实体实例,并且无法知道getter将在所有实例中返回一个常量值。

我又用CCD_ 9代替了CCD_。

我为我的特定场景找到了一个变通方法:

public IEnumerable<HouseEntity> GetHouses() 
{ 
List<int> categoryPermissions = new List<int>() {1, 2, 3}; // usually obtained through service 
int category = (new HouseEntity()).DataCategory;
return context.HouseEntities
.Where(he => categoryPermissions.Contains(category) || he.IsPublic == true )
.ToList(); 
}

尽管这看起来有点不合理,这种方法是必要的,因为我需要能够编写一种方法来生成通用where子句Expressions,它不与具体的Entity类一起工作,而是与Interface一起工作,强制实现它的Entity通过未映射的属性对自己进行分类,并提供对一些常见属性(如IsPublic列(的访问。

谢谢大家的建议!

最新更新