C#Linq - 获取非空集合的对象

Act*_*tic 9 c# linq

我有:

private Dictionary<int, ?olor[]> colorSet = new Dictionary<int, ?olor[]>()
{
   {1, new ?olor[2] {?olor.Red, ?olor.Green}},
   {2, new ?olor[2] {?olor.Yellow, ?olor.Blue}},
   ...
};

public class Graph
{
   public ?olor ?olor { get; set; }
   public ICollection<Point> Points { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

1)我如何List<Graph>从数据库中获取Points非空的?

List<Graph> graphs = context.Graphs.Where(g => g.Points.Count > 0).ToList()
Run Code Online (Sandbox Code Playgroud)

2)如何执行?

List<Graph> graphs = context.Graphs.Where(g => colorSet[1].Contains(g.Color)).ToList()
Run Code Online (Sandbox Code Playgroud)

例外是:

LINQ to Entities 无法识别方法'...'方法,并且此方法无法转换为商店表达式.

Pan*_*vos 2

在EF中使用Enumerable.Contains()没有问题。这是无法翻译的String.Contains 。

第二个查询的问题在于您将 LINQ 运算符与对象访问代码混合在一起,特别是colorSet[1]. LINQ to EF 不会尝试执行此代码,也不知道如何将其转换为 SQL。

解决方案是首先将 colorSet 值存储到变量中:

var colors = colorSet[1];
List<Graph> graphs = context.Graphs
                            .Where(g => colors.Contains(g.Color))
                             .ToList();
Run Code Online (Sandbox Code Playgroud)

LINQ to EF 知道转换Enumerable<T>.Contains()AND Color IN (0,1)子句

这假设您至少使用 EF 5, Color是一个枚举并且 Point 是一个自定义类,例如:

public enum Color
{
    Red,
    Green,
    Blue,
    Yellow
}
public class Point
{
    public int Id { get; set; }
    public int X { get; set; }
    public int Y { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

更新

对于第一个问题,您可以使用以下方法检索具有任何点的图形Any()

var graphs=context.Graphs
                  .Where(g => g.Points.Any())
                  .ToList();
Run Code Online (Sandbox Code Playgroud)

Linq to EF 将生成带有子句的 SQL 语句,WHERE EXISTS例如

WHERE  EXISTS (SELECT 
    1 AS [C1]
    FROM [dbo].[Points] AS [Extent2]
    WHERE [Extent1].[Id] = [Extent2].[Graph_Id]
)
Run Code Online (Sandbox Code Playgroud)

这将返回具有点的图形,但不返回点本身。Points当您尝试访问Graph 对象的属性时,这些将以惰性方式加载。如果您只想访问少数Points属性,这可能会提高性能,但如果您想访问所有属性,这会导致大量查询(N+1 问题)

如果您还想加载点,则需要使用该Include()方法,例如:

var graphs=context.Graphs
                  .Include(g => g.Points)
                  .Where(g => g.Points.Any())
                  .ToList();
Run Code Online (Sandbox Code Playgroud)

这将在图形和点之间执行左连接,并在单个查询中返回所有数据。