这更多是技术性的“操作方法”或“最佳方法”问题。
我们当前要求从数据库中检索记录,将它们放入“内存中”列表,然后对数据执行一系列计算,即最大值,平均值和一些更具体的自定义统计信息。
将数据放入“内存中”列表不是问题,因为我们使用NHibernate作为我们的ORM,并且它可以很好地从数据库中检索数据。我正在寻求的建议是我们应该如何最好地对结果数据列表进行计算。
理想情况下,我想为每个统计信息创建一个方法,MaximumValue(),AverageValueUnder100(),MoreComplicatedStatistic()等等。当然,将所需的变量传递给每个方法并让它返回结果。这种方法也可以使单元测试变得轻而易举,并为我们提供了极好的覆盖范围。
如果我们为每个计算执行LINQ查询,或者应该在尽可能少的LINQ查询中合并每个统计方法的次数,那么是否会有性能损失。例如,将数据列表传递给名为AverageValueBelow100的方法,然后将整个数据列表传递给另一个方法AverageValueBelow50(当它们可以通过一个LINQ查询有效地执行时)没有多大意义。
如何在不牺牲性能的情况下实现高水平的粒度和分离?
任何建议......问题是否足够明确?
答案 0 :(得分:1)
根据计算的复杂程度,最好在数据库中执行此操作。如果它显着复杂,您需要将其作为对象引入并引发开销,您可能希望避免对结果集进行多次迭代。您可能需要考虑使用Aggregate。如果有,请参阅http://geekswithblogs.net/malisancube/archive/2009/12/09/demystifying-linq-aggregates.aspx进行讨论。您可以单独对每个聚合进行单元测试,但随后(可能)在一次迭代中投影多个聚合。
答案 1 :(得分:1)
我不同意最好“在数据库中完成所有操作”。
编写良好的Linq查询将导致对数据库执行良好的SQL查询,这应该是性能良好的(如果你不打算做dwh的东西)。这假设您使用的是Liniber Provider for NHibernate,而不是Linq to Objects。
它确实看起来不错,您可以轻松更改它并将您的业务逻辑保存在一个位置。
如果这对您的需求来说太慢,您可能会检查创建的SQL代码并调整您的linq查询,尝试预编译它们,最后您仍然可以返回编写心爱的存储过程 - 并开始在整个地方传播您的业务逻辑。
是否会有性能受损?是的,你可能会损失几毫秒,但这是否值得为分离逻辑付出代价?
答案 2 :(得分:0)
要回答“我想为每个统计数据创建一个方法”的问题,我建议你建立一种统计学家类。这是一些表达这个想法的伪代码:
class Statistician
{
public bool MustCalculateFIRSTSTATISTIC { get; set; } // Please rename me!
public bool MustCalculateSECONDSTATISTIC { get; set; } // Please rename me!
public void ProcessObject(object Object) // Replace object and Rename
{
if (MustCalculateFIRSTSTATISTIC)
CalculateFIRSTSTATISTIC(Object);
if (MustCalculateFIRSTSTATISTIC)
CalculateSECONDSTATISTIC(Object);
}
public object GetFIRSTSTATISTIC() // Replace object, Rename
{ /* ... */ }
public object GetSECONDSTATISTIC() // Replace object, Rename
{ /* ... */ }
private void CalculateFIRSTSTATISTIC(object Object) // Replace object
{ /* ... */ }
private void CalculateSECONDSTATISTIC(object Object) // Replace object
{ /* ... */ }
}
我是否必须这样做,我可能会尝试使它成为通用的并使用委托的集合而不是方法,但由于我不知道你的上下文,我会留下它。另请注意,我只使用了对象类的Object成员,但这只是因为我并不是建议您使用DataRows,Entities或者不是;我会把这个留给那些在这个问题上了解更多的人!