Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.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 to实体的可重用函数_C#_Linq_Linq To Sql_Linq To Entities - Fatal编程技术网

C# 用于Linq to实体的可重用函数

C# 用于Linq to实体的可重用函数,c#,linq,linq-to-sql,linq-to-entities,C#,Linq,Linq To Sql,Linq To Entities,我有一些统计代码,我想在不同的地方使用它们来计算进度结果的成功/失败百分比。我最近在代码中发现了一个bug,这是因为它在每个LINQ语句中都被复制了,然后我决定最好使用通用代码来实现这一点。当然,问题是,当在SQL server上执行普通函数时,会抛出NotSupportedException,因为该函数在SQL server中不存在 如何编写在SQL server上执行的可重用统计代码,或者这是不可能的 下面是我为这个结果编写的代码 它的用法类似于结果是IQueryable,并引发异常: sc

我有一些统计代码,我想在不同的地方使用它们来计算进度结果的成功/失败百分比。我最近在代码中发现了一个bug,这是因为它在每个LINQ语句中都被复制了,然后我决定最好使用通用代码来实现这一点。当然,问题是,当在SQL server上执行普通函数时,会抛出NotSupportedException,因为该函数在SQL server中不存在

如何编写在SQL server上执行的可重用统计代码,或者这是不可能的

下面是我为这个结果编写的代码

它的用法类似于结果是IQueryable,并引发异常:

schedule.SuccessRatePercentage = (int)Math.Ceiling(results.Average(r => r.CalculateSuccessRatePercentage()));
schedule.CoveragePercentage = (int)Math.Ceiling(results.Average(r => r.CalculateCoveragePercentage()));
或者像这样工作,因为我们在一个结果上做这件事

retSchedule.SuccessRatePercentage = (byte)Math.Ceiling(result.CalculateSuccessRatePercentage());
retSchedule.CoveragePercentage = (byte)Math.Ceiling(result.CalculateCoveragePercentage());
编辑

根据@Fred的回答,我现在有以下代码,它适用于IQueryable

唯一的问题,尽管是一个小问题,是该代码将不适用于单个结果,即

retSchedule.SuccessRatePercentage = (byte)Math.Ceiling(/* How do I use it here for result */);

您不能将函数传递给SQL—您需要在实际的SQL数据库上声明函数,然后从代码中调用该函数

您可以做/尝试的是:

Expression<Func<Result, double>> CalculateCoveragePercentage()
{
    return r => r.PresentCount == 0 ? 0 : (r.ExecutedCount * 100.0 / r.PresentCount);
}
更新2:

为了使它能够处理单个结果,或者在任何情况下,都需要将其传递到接受表达式的子句中。例如Select,其中,显然,任何不返回结果的内容都是平均值

从我的头顶上看,我肯定我错过了一些:

列表:ToArray、ToDictionary、ToList、ToLookup

单个结果:First,FirstOrDefault,Single,SingleOrDefault,Last,LastOrDefault

计算:计数、求和、最大值、最小值

因为上面的子句返回结果,所以据我所知,它们只接受谓词一个只能返回'true'或'false'的函数

您可能碰巧用.averageCalculateCoreragePercentage正确地计算了它

因此,如果要使用.FirstOrDefault获得单个结果,则应在该结果之前的select子句中传入表达式:.SelectCalculateCoreragePercentage.FirstOrDefault。也就是说,如果您不需要实际实体,只需要计算。但是请注意,如果没有结果,这个特定示例将返回0。您可能想要也可能不想要这种行为

当然,如果您已经有了结果,它不再是IQueryable,那么您可以简单地执行以下操作:

var coveragePercentage = CalculateCoveragePercentage().Compile().Invoke(result);

但这有点违背了表达式的目的——在这种情况下,您只需在结果类中添加一个方法,用于计算给定实例的覆盖率百分比。

这很有效,谢谢,这是一个非常好的解决方案。虽然我不能用同样的代码来处理一个结果,但是有什么想法吗?但至少所有的代码现在都在一个地方,你能把你试图执行的代码添加到你的问题中吗?不确定你是否看到了我的编辑。你用我提供的SelectCalculateCoreveragePercentage语法试过了吗?嘿,Fred,它在没有编辑的情况下适用于LINQ,只是不适用于单个POCO结果。我用更多的道歉更新了我的问题,我搞砸了。它再次更新-下面的“更新2”信息应该可以帮助您解决问题。您是否可以包含变量的声明,以便我们可以查看它们的数据类型?
Expression<Func<Result, double>> CalculateCoveragePercentage()
{
    return r => r.PresentCount == 0 ? 0 : (r.ExecutedCount * 100.0 / r.PresentCount);
}
// Assuming you have Results declared as a DbSet or IDbSet, such as:
DbSet<Result> Results

// You could do something like this (just to illustrate that
// it would be interpreted rather than executed):
List<double> allCoveragePercentages = Results.Select(CalculateCoveragePercentage)
                                             .ToList();
var coveragePercentage = CalculateCoveragePercentage().Compile().Invoke(result);