我有:
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((