Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.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# 如何使LINQ到EF查询更高效_C#_Linq_Entity Framework - Fatal编程技术网

C# 如何使LINQ到EF查询更高效

C# 如何使LINQ到EF查询更高效,c#,linq,entity-framework,C#,Linq,Entity Framework,我有以下查询,可以在我们的房地产数据库中找到特定房源的降价。我想知道这个查询是否可以更有效地完成。最终目标是获得最近2次价格变动的房源,其中最近的价格变动小于之前的价格变动。我的问题是: var PriceDrops = idxContext.ListingPriceChanges .Where(a => a.DateAdded >= LastRunTime && ListingIDsChunk.Contains(a.ListingID)) .Gr

我有以下查询,可以在我们的房地产数据库中找到特定房源的降价。我想知道这个查询是否可以更有效地完成。最终目标是获得最近2次价格变动的房源,其中最近的价格变动小于之前的价格变动。我的问题是:

var PriceDrops = idxContext.ListingPriceChanges
     .Where(a => a.DateAdded >= LastRunTime && ListingIDsChunk.Contains(a.ListingID))
     .GroupBy(g => g.ListingID)
     .Where(g => g.Count() > 1 && g.OrderByDescending(a => a.DateAdded).FirstOrDefault().ListPrice < g.OrderByDescending(a => a.DateAdded).Skip(1).FirstOrDefault().ListPrice)
     .SelectMany(g => g.OrderByDescending(a => a.DateAdded).Take(2)).ToList();
ListingPriceChanges表中当前有3239193条记录

如果你需要更多信息,请告诉我。在上面的查询中,我用REMOVED-2000-IDs文本替换了2000-id

我正在使用EF5.0和.NET4.5

ListingPriceChanges表定义为:

[ListingPriceChangeID] [int] IDENTITY(1,1) NOT NULL,
[ListingID] [int] NOT NULL,
[ListPrice] [money] NOT NULL,
[PriceChangeDate] [datetime2](7) NULL,
[DateAdded] [datetime2](7) NOT NULL

字段ListingID是Listings表的FK引用。ListingID字段中还有一个包含PriceChangeDate的表索引。

我现在无法测试,但我相信您可以执行以下操作:

var PriceDrops = idxContext.ListingPriceChanges
    .Where(a => a.DateAdded >= LastRunTime && ListingIDsChunk.Contains(a.ListingID))
    .GroupBy(g => g.ListingID)
    .Where(g => g.Count() > 1)
    .Select(g => g.OrderByDescending(a => a.DateAdded).Take(2))
    .Where(g => g.First().ListPrice < g.Skip(1).First().ListPrice)
    .SelectMany(g => g)
    .ToList();

这将减少子查询的数量,我相信这可能有助于提高整体性能。它的操作也更简单。

我现在无法测试,但我相信您可以执行以下操作:

var PriceDrops = idxContext.ListingPriceChanges
    .Where(a => a.DateAdded >= LastRunTime && ListingIDsChunk.Contains(a.ListingID))
    .GroupBy(g => g.ListingID)
    .Where(g => g.Count() > 1)
    .Select(g => g.OrderByDescending(a => a.DateAdded).Take(2))
    .Where(g => g.First().ListPrice < g.Skip(1).First().ListPrice)
    .SelectMany(g => g)
    .ToList();

这将减少子查询的数量,我相信这可能有助于提高整体性能。它也更容易理解。

通过修改Reed的答案,我能够将2000个列表批次的平均执行时间从20秒减少到13秒。我使用了下面的解决方案,将平均执行时间降低到3秒左右。我需要在选择初始收藏后但在比较ListPrice之前调用.ToList

var PriceDrops = idxContext.ListingPriceChanges
        .Where(a => a.DateAdded >= LastRunTime && ListingIDsChunk.Contains(a.ListingID))
    .GroupBy(g => g.ListingID)
    .Where(g => g.Count() > 1)
    .Select(g => g.OrderByDescending(a => a.DateAdded).Take(2))
    .ToList()
    .Where(g => g.First().ListPrice < g.Last().ListPrice)
    .SelectMany(g => g)
    .ToList();

通过修改Reed的答案,我能够将2000个列表批处理的平均执行时间从20秒降低到13秒。我使用了下面的解决方案,将平均执行时间降低到3秒左右。我需要在选择初始收藏后但在比较ListPrice之前调用.ToList

var PriceDrops = idxContext.ListingPriceChanges
        .Where(a => a.DateAdded >= LastRunTime && ListingIDsChunk.Contains(a.ListingID))
    .GroupBy(g => g.ListingID)
    .Where(g => g.Count() > 1)
    .Select(g => g.OrderByDescending(a => a.DateAdded).Take(2))
    .ToList()
    .Where(g => g.First().ListPrice < g.Last().ListPrice)
    .SelectMany(g => g)
    .ToList();

用所提供的信息来回答这个问题几乎是不可能的。我们不知道它实际生成的是什么SQL。SQL现在需要多长时间。执行计划是什么。现在的物理数据结构是什么。还有更多问题要问。简短回答:编写自定义SQL或存储过程。@RobertHarvey,但这不是LINQ。这段代码甚至不复杂,没有理由回退到手动编写SQL。OP甚至没有说他有表演问题。他只是在问如何改进这个查询。@Ricketts您在这里有性能问题吗,还是出于好奇而问?您的目标是什么版本的EF和.Net?已知包含2000个或更多元素时速度较慢:这可能是性能不佳的原因之一。真正让它变慢的不是SQL本身,而是从LINQ到SQL的转换。其中包含的已翻译查询不会被缓存。您可以通过在查询的末尾使用ToString而不是ToList来缩小查询范围,这只会强制生成SQL而不执行它。问题是ToString是否很慢。用提供的信息很难回答这个问题。我们不知道它实际生成的是什么SQL。SQL现在需要多长时间。执行计划是什么。现在的物理数据结构是什么。还有更多问题要问。简短回答:编写自定义SQL或存储过程。@RobertHarvey,但这不是LINQ。这段代码甚至不复杂,没有理由回退到手动编写SQL。OP甚至没有说他有表演问题。他只是在问如何改进这个查询。@Ricketts您在这里有性能问题吗,还是出于好奇而问?您的目标是什么版本的EF和.Net?已知包含2000个或更多元素时速度较慢:这可能是性能不佳的原因之一。真正让它变慢的不是SQL本身,而是从LINQ到SQL的转换。其中包含的已翻译查询不会被缓存。您可以通过在查询的末尾使用ToString而不是ToList来缩小查询范围,这只会强制生成SQL而不执行它。问题是ToString是否很慢。这将不起作用,因为.Last在EF中不受支持。要获得第二条记录以比较我能说出的标价,唯一的方法是使用Skip1,但是,如果不先排序结果,就不能使用Skip1。@Ricketts我已经排序过了-所以你应该可以使用Skip1。首先,然后-将编辑注释选择在athat的正上方…我相信您只是订购单个组,而不是整个集合。我已经尝试更改为skip,但它引发了以下异常:“skip”方法仅支持LINQ to Entities中的排序输入。方法“OrderBy”必须在方法“Skip”之前调用。此外,您也不能使用First,您需要更改为FirstOrDefault。自定义SQL或存储过程看起来似乎是更好的选择。这将不起作用,因为EF中不支持.Last。获得第二条记录以比较ListPric的唯一方法
我能告诉你的是使用Skip1,但是,如果不先对结果进行排序,你就不能使用Skip1。@Ricketts我已经对结果进行了排序,所以你应该可以使用Skip1。首先,然后-将编辑注释,选择在athat正上方的位置…我相信你只对单个组进行排序,而不是对整个集合进行排序。我已经尝试更改为skip,但它引发了以下异常:“skip”方法仅支持LINQ to Entities中的排序输入。方法“OrderBy”必须在方法“Skip”之前调用。此外,您也不能使用First,您需要更改为FirstOrDefault。自定义SQL或存储过程开始看起来是更好的选择。