Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使EntityFramework关系易读?_C#_Performance_Entity Framework - Fatal编程技术网

C# 如何使EntityFramework关系易读?

C# 如何使EntityFramework关系易读?,c#,performance,entity-framework,C#,Performance,Entity Framework,让我们假设我有这些类: public class Car { public int CarId { get; set} public virtual ICollection<Door> Doors { get; set} } public class Door { public int DoorId { get; set} public decimal Weight { get; set} public int CarId { get; set}

让我们假设我有这些类:

public class Car
{
  public int CarId { get; set} 
  public virtual ICollection<Door> Doors { get; set} 
}

public class Door
{
   public int DoorId { get; set} 
   public decimal Weight { get; set} 
   public int CarId { get; set} 
}
正如我在EFTraceLog中看到的,他做了一些类似的事情 从CarId=@的门中选择*。。。 并在应用程序服务器上计算“Min”,而不是在db服务器上

我有非常大的汽车和门表,所以这个操作持续几分钟。 但是如果我把代码改成这个

foreach ( var car in db.Cars )
{
   var x = db.Doors.Where(d => d.CarId == car.CarId).Min(d => d.Weight);
}
然后是几秒钟

为什么会有如此大的差异?如何解决? 这里的问题是写起来要简单得多

var x = car.Doors.Min(d => d.Weight);
然后

更新

我们使用的是实体框架5.0

更新2

我试过这些变体,它们很慢

var x = car.Doors.Select(door => door.Weight).Min();
var x = car.Doors.OrderBy(x => x.Weight).Select(x => x.Weight).FirstOrDefault();
var x = car.Doors.OrderBy(x => x.Weight).Select(x => x.Weight).First();
var x = car.Doors.OrderBy(x => x.Weight).FirstOrDefault().Weight;
var x = car.Doors.OrderBy(x => x.Weight).First().Weight;
只有这个快

var x = db.Doors.Where(d => d.CarId == car.CarId).Min(d => d.Weight);
更新3

最佳查询生成此sql

declare @p__linq__0 Int32 = cast(N'204' as Int32);

SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
MIN([Extent1].[Weight]) AS [A1]
FROM [dbo].[Doors] AS [Extent1]
WHERE [Extent1].[CarId] = @p__linq__0
) AS [GroupBy1]

Linq to Entities
仅支持
Min
而不支持额外的投影。这意味着您当前的
Min
将使用Linq To对象调用(导致
Doors
集合具体化-因此您在日志中看到生成的SQL)

发件人:

支持:

TSource Min<TSource>(this IQueryable<TSource> source)
TResult Min<TSource, TResult>(this IQueryable<TSource> source,Expression<Func<TSource, TResult>> selector)
更新:

TSource Min<TSource>(this IQueryable<TSource> source)
TResult Min<TSource, TResult>(this IQueryable<TSource> source,Expression<Func<TSource, TResult>> selector)
显然,
entityframework
不支持带投影的延迟加载,这意味着无论何时加载引用实体(
Car.Doors
,在您的情况下),框架延迟加载其所有数据,并且您无法选择要加载的属性(
Weight

这就是这两个调用之间存在差异的原因:

// Accessing 'Doors' thru 'Car' means 'Lazy Load'
car.Doors.Select(x => x.Weight).Min();
但是,

您还可以尝试访问
Car.Doors
Eager Load
Doors

foreach ( var car in db.Cars.Include(x => x.Doors))
{
   var x = car.Doors.Select(x => x.Weight).Min();
}
(我使用了Servy建议的
Min
的缩短选项)

根据,EF不支持进行投影的
Min
重载,但您可以先使用
Select
执行投影,以获得所需的结果:

var minWeight = db.Doors.Select(door => door.Weight).Min();

我无法验证,所以我已删除。我尝试了car.Doors.OrderBy(x=>x.Weight)。选择(x=>x.Weight)。First();和car.Doors.OrderBy(x=>x.Weight.First().Weight。两者都没用。仍然是同一个查询:从CarId=@…@YegorRazumovsky的Doors中选择*这是一个不同于向您建议的查询。EF不支持
First
,仅支持
FirstOrDefault
。已试用的car.Doors.OrderBy(x=>x.Weight)。选择(x=>x.Weight)。FirstOrDefault();同样的故事我也修改了我的答案。@YegorRazumovsky听起来你的查询提供程序配置不正确。是否正确翻译了任何查询?该特定表上的其他查询是否正确转换了?这个查询非常有效,var x=db.Doors.Where(d=>d.CarId==car.CarId).Min(d=>d.Weight)@YegorRazumovsky以及它转换成了什么样的SQL?@YegorRazumovsky还请确保
Weight
是一个索引列。这可能只是因为,如果不是索引,那么由于您拥有的数据量,找到最小权重是一项昂贵的操作。显然,即使一切正常,对ID的过滤也会快得多;这不是一个恰当的比较。问题是在每种情况下是否正确地将其转换为SQL。权重列具有索引
Where
(您的最后一行)语句生成的SQL是什么?
foreach ( var car in db.Cars.Include(x => x.Doors))
{
   var x = car.Doors.Select(x => x.Weight).Min();
}
var minWeight = db.Doors.Select(door => door.Weight).Min();