gpt4 book ai didi

c# - Linq to SQL 计数分组元素生成超时

转载 作者:可可西里 更新时间:2023-11-01 07:57:37 25 4
gpt4 key购买 nike

我有一个看起来像这样的表:

FruitID | FruitType
23 | 2
215 | 2
256 | 1
643 | 3

我想通过 FruitType 获得一个名为 TheFruitIDsFruitIDs 列表。这是我的:

var TheCounter = (from f in MyDC.Fruits    
where TheFruitIDs.Contains(f.FruitID)
group f by 0 into TheFruits
select new MyCounterMode()
{
CountType1 = (int?) TheFruits.Where(f => f.FruitType == 1).Count() ?? 0,
CountType2 = (int?) TheFruits.Where(f => f.FruitType == 2).Count() ?? 0,
.... all the way to CountType6
}).Single();

此代码有效,但问题是有时我会收到超时错误,因为查询运行时间太长。如何更改此代码以避免超时问题?

最佳答案

最简单的查询方法是按 FruitType 分组,然后计算行数:

var countsDictionary = MyDC
.Fruits
.Where(f => TheFruitIDs.Contains(f.FruitID))
.GroupBy(
f => f.FruitType,
(fruitType, fruits) => new { FruitType = fruitType, Count = fruits.Count() }
)
.ToDictionary(c => c.FruitType, c => c.Count);

这将有效地创建以下字典(假设 where 部分没有排除任何数据):

FruitType | Count----------+------1         | 12         | 23         | 1

If you really want to collapse this into a single object having counts for specific fruit types you then have to create this object:

var TheCounter = new {
CountType1 = countsDictionary.ContainsKey(1) ? countsDictionary[1] : 0,
CountType2 = countsDictionary.ContainsKey(2) ? countsDictionary[2] : 0,
CountType3 = countsDictionary.ContainsKey(3) ? countsDictionary[3] : 0
};

您的查询中还有另一件事可能导致性能问题,可能会导致超时:where 部分中的水果 ID 列表包含在查询中,如果该列表非常大,它可能会减慢您的查询速度。除非您根据先前对数据库的查询创建此列表,否则您无能为力。在这种情况下,您应该尽量避免将水果 ID 列表拉到客户端。相反,您应该将选择 ID 的查询与计算类型的查询结合起来。这将确保整个查询在服务器端执行。

您似乎很关心代码的结构变化。只要您正在创建匿名对象,就很难编写可重用代码。您可以考虑只使用带有计数或类似内容的字典。另一种选择是创建一个带有计数的动态对象。就个人而言,我不喜欢这个解决方案,但您可能会发现它很有用。

为了简化代码,需要一个类来存储计数:

class TypeCount {

public TypeCount(Int32 type, Int32 count) {
Type = type;
Count = count;
}

public Int32 Type { get; private set; }

public Int32 Count { get; private set; }

}

具有基于元组序列的属性 CountType0CountType1CountType2 等的动态对象:

class CountsDictionary : DynamicObject {

readonly IDictionary<Int32, Int32> counts;

public CountsDictionary(IEnumerable<TypeCount> typeCounts) {
if (typeCounts== null)
throw new ArgumentNullException("typeCounts");
this.counts = typeCounts.ToDictionary(c => c.Type, c => c.Count);
}

public override Boolean TryGetMember(GetMemberBinder binder, out Object result) {
Int32 value;
if (binder.Name.StartsWith("CountType") && Int32.TryParse(binder.Name.Substring(9), NumberStyles.None, CultureInfo.InvariantCulture, out value) && value >= 0) {
result = this.counts.ContainsKey(value) ? this.counts[value] : 0;
return true;
}
result = 0;
return false;
}

}

创建动态对象的扩展方法:

static class CountExtensions {

public static dynamic ToCounts(this IEnumerable<TypeCount> typeCounts) {
return new CountsDictionary(typeCounts);
}

}

综合起来:

var counts = MyDC
.Fruits
.Where(f => TheFruitIDs.Contains(f.FruitID))
.GroupBy(
f => f.FruitType,
(fruitType, fruits) => new TypeCount(fruitType, fruits.Count())
)
.ToCounts();

然后您可以检索属性 counts.CountType1counts.CountType2counts.CountType3。其他 count.CountType# 属性将返回 0。但是,由于 counts 是动态的,您不会获得任何智能感知。

关于c# - Linq to SQL 计数分组元素生成超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31947209/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com