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( 如何从Points不为空的数据库中获取List<Graph>

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无法识别方法"…"方法,以及此方法无法转换为存储表达式。

在EF中使用Enumerable.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是一个枚举,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; }
}

更新

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

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

Linq到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();

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

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

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

请参阅LINQ to SQL 中的Using contains((

相关内容

  • 没有找到相关文章

最新更新