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

时间:2015-05-27 06:48:14

标签: 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; }
}

1)如何从List<Graph>不为空的数据库中获取Points

List<Graph> graphs = context.Graphs.Where(g => g.Points.Count > 0).ToList()

2)如何执行?

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

例外是:

  

LINQ to Entities无法识别方法&#39; ...&#39;方法,和   此方法无法转换为商店表达式。

2 个答案:

答案 0 :(得分:2)

.Contains不能用在数据库上下文的.Where子句中。您可以使用.Any或.All进行比较。

List<Graph> graphs = context.Graphs.Where(g => colorSet[1].Any(c => c.Color == g.Color)).ToList()

请参阅Using contains() in LINQ to SQL

答案 1 :(得分:1)

在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();

LINQ to EF知道将Enumerable<T>.Contains()翻译成AND Color IN (0,1)子句

这假定您至少使用EF 5,Color是枚举并指向自定义类,例如:

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; }
}

<强>更新

关于第一个问题,您可以使用Any()

检索包含任意点的图表
var graphs=context.Graphs
                  .Where(g => g.Points.Any())
                  .ToList();

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

WHERE  EXISTS (SELECT 
    1 AS [C1]
    FROM [dbo].[Points] AS [Extent2]
    WHERE [Extent1].[Id] = [Extent2].[Graph_Id]
)

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

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

var graphs=context.Graphs
                  .Include(g => g.Points)
                  .Where(g => g.Points.Any())
                  .ToList();

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