我有:
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无法识别方法'...'方法,并且此方法无法转换为商店表达式.
在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)
这将在图形和点之间执行左连接,并在单个查询中返回所有数据。
| 归档时间: |
|
| 查看次数: |
253 次 |
| 最近记录: |