名为MyDB的My Db有5个表:MSize,MModel,Met,MResult,SResult。它们的连接如下:
MSize与MModel有一个公共字段MSizeId。
MModel与具有MModelId的Met链接。
Met可以基于MId与MResult链接。
类似地,SResult可以与SResultId上的MResult链接。
我的目标是获得所有项(Msize表中的描述字段)的Acc(十进制数据类型)> = 70和<= 130(按描述分组)的平均准确性。
这是我的SQL查询:
use MyDB;
SELECT a.[Description],AVG(CASE WHEN d.[Acc] >= 70 AND d.[Acc] <= 130 THEN d.[Acc] END)
FROM MSize a
INNER JOIN MModel b ON a.MSizeId = b.MSizeId
INNER JOIN Met c ON b.MModelId = c.MModelId
INNER JOIN MResult d ON c.MId = d.MId
INNER JOIN SResult e ON d.SResultId = e.SResultId
GROUP BY a.Description
此查询为我在SQL Server上提供了正确的结果。
我一直在努力编写相同的LINQ查询。问题来自于SQL CASE语句。我不想指定CASE的错误结果,这意味着,如果d.acc不在SQL查询中指定的范围内,则将其丢弃。
假定所有Model类和字段都与这些DBtables和列具有相同的名称。给定SQL语句的LINQ查询是什么?
您可以在大括号中填写代码:
using (var db = new MyDBContext()){ }
此处MyDBContext指的是LINQ生成的局部类数据模型模板
答案 0 :(得分:0)
您不必费心编写这些类,我也不会为您这样做。
显然,您有一个MSizes序列,其中每个Msize都有零个或多个MModel。每个MModel都有零个或多个Mets,每个Met都有零个或多个MResult,每个MResult都有一个Acc。
您还忘了用文字写下您的要求,现在我不得不从您的SQL查询中提取它
似乎您希望每个MSize的描述都具有其所有Acc的平均值,其值在70到130之间。
如果使用实体框架,则可以使用virtual ICollection
,它使工作变得相当容易。我将分两个步骤进行操作,因为下面我对GroupJoin进行了相同的操作,而没有使用ICollection。两种方法的第二部分是相同的。
首先,我将获取每个MSize的描述以及该MSize的MModel的Mets的MResult中所有更深的Acc:
var descriptionsWithTheirAccs = dbContext.MSizes.Select(msize => new
{
Description = msize.Description,
// SelectMany the inner collections until you see the Accs
Accs = mSize.Mmodels.SelectMany(
// collection selector:
model => model.Mets,
// result selector: flatten MResults in the Mets
(model, mets) => mets
.SelectMany(met => met.MResults,
// result Selector: from every mResult take the Acc
(met, mResults) => mResults
.Select(mResult => mResult.Acc)));
现在,我们有了每个MSize的描述,以及其中包含的所有Acc, 我们可以丢弃所有我们不需要的Accs,然后平均剩余的Accs:
var result= descriptionsWithTheirAccs.Select(descriptionWithItsAccs => new
{
Description = descriptionWithItsAccs.Description,
Average = descriptionWithItsAccs.Accs
.Where(acc => 70 <= acc && acc <= 130)
// and the average from all remaining Accs
.Avg(),
});
如果您无权访问ICollection,则必须自己进行Groupjoin,如果您有很多表,这看起来就很可怕:
var descriptionsWithTheirAccs = dbContext.MSizes.GroupJoin(dbContext.MModels,
msize => msize.MSizeId,
mmodel => mmodel.MSizeId,
(msize, mmodels) => new
{
Description = msize.Description,
Accs = mmodels.GroupJoin(dbContext.Mets,
mmodel => mModel.MModelId,
met => met.MModelId,
(mmodel, metsofThisModel) => metsOfThisModel
.GroupJoin(dbContext.MResults,
met => met.MetId
mresult => mresult.MetId,
// result selector
(met, mresults) => mResult.Select(mresult => mresult.Acc))),
});
现在您有了DescriptionsWithTheirAccs,则可以使用上面的Select计算平均值。