C# LINQ到实体扩展;多个子查询、联接和case语句

C# LINQ到实体扩展;多个子查询、联接和case语句,c#,linq,C#,Linq,我已经在谷歌上彻底搜索了我最新的LINQ产品的例子(“嗨,我是LINQ的新手”)。我会把我浏览过的页面列表留给你 下面是我想要实现的示例SQL: use myDB; go declare @requestedDay datetime = convert(datetime, (convert(varchar(10), getdate(), 101)), 101) declare @type1 int = 20 ;with currentQuery as ( select case when z

我已经在谷歌上彻底搜索了我最新的LINQ产品的例子(“嗨,我是LINQ的新手”)。我会把我浏览过的页面列表留给你

下面是我想要实现的示例SQL:

use myDB;
go

declare @requestedDay datetime = convert(datetime, (convert(varchar(10), getdate(), 101)), 101)
declare @type1 int = 20

;with currentQuery as ( select
case when z.someID = @type1 and bet.someValue is null then 1
    else 0 end as count1,
case when z.someID = @type1 and bet.someValue = alef.otherID then 1
    else 0 end as count2,
from dbo.Work as dalet
    left join dbo.Workers as z on alef.workerAssignedID = z.ID
    left join dbo.Contracts as alef on alef.workOrderID = gimel.ID
    left join dbo.Subcontracts as bet on alef.WorkOrderID = alef.WorkOrderID 
                  and alef.WorkerAssignedID = dalet.WorkerID 
where convert(varchar(10),alef.dateTimeofWork,101) = @requestedDay),
futureQuery as ( select
case when gimel.text_EN like '%blah%' and bet.someValue is null then 1
    else 0 end as count3,
case z.someID = @type1 and bet.someValue = alef.otherID then 1
    else 0 end as count4,
from dbo.Work as dalet
    left join dbo.Workers as z on dalet.workerAssignedID = z.ID
    left join dbo.Contracts as alef on dalet.workOrderID = alef.ID
    left join dbo.Subcontracts as bet on dalet.WorkOrderID = bet.WorkOrderID and wa.WorkerAssignedID = wr.WorkerID 
    left join dbo.Lookups as gimel on dalet.skillID = gimel.ID
where convert(datetime,(convert(varchar(10),alef.dateTimeofWork,101)),101) > @requestedDay)
select sum(count1) as prop1name, sum(count2) as prop2name, 
sum(count3) as prop3name, sum(count4) as prop4name
from currentQuery, futureQuery
当然,这是一个大得多的查询的简化版本。它只包含我需要的基本内容。名字可能会让人困惑,但我在寻找一些独特的东西。他们还与下面的林克表亲相配

…这就是说,这就是我被困住的地方:(“我迄今为止所尝试的:”)我已经包括了一些描述我正在努力思考的问题的评论

//snip injection stuff above
    public IQueryable<DailyCasaLatinaReport> DailyCasaLatina(DateTime dateRequested)
    {
        IQueryable<DailyCasaLatinaReport> query;

        var daletQ = waRepo.GetAllQ();
        var zQ = zRepo.GetAllQ();
        var alefQ = alefRepo.GetAllQ();
        var betQ = betRepo.GetAllQ();
        var gimelQ = gimelRepo.GetAllQ();

        int type1 = 20;
        int type2 = 21;

        query = daletQ
                   .GroupJoin(gimelQ, dalet => dalet.skillID, look => look.ID,
                                 (dalet, look) => new
                                 {
                                     dalet,
                                     enSkillText = look.FirstOrDefault().text_EN
                                 }) //currently envisioning a left outer join of
                                    //all .skillID, with English text available
                                    //for column and condition matches from the
                                    //next three joins.
                   .GroupJoin(betQ, gimel => gimel.dalet.workOrderID, wr => wr.WorkOrderID,
                                  (gimel, wr) => new
                                  {
                                      gimel,
                                      reqWorkerID = wr.FirstOrDefault().WorkerID,
                                      reqOrderID = wr.FirstOrDefault().WorkOrderID
                                  }) //now envisioning a join on the original table
                                     //where any match in workerID is joined. THIS
                                     //IS A PROBLEM, I actually need to join on two
                                     //conditions to avoid duplicates.
                   .GroupJoin(alefQ, bet => bet.gimel.dalet.workOrderID, wo => wo.ID,
                                  (bet, wo) => new
                                  {
                                      bet,
                                      timeOfWork = wo.FirstOrDefault().dateTimeofWork
                                  }) //now envisioning yet another join where the
                                     //dateTimeofWork property from woQ is stamped
                                     //onto all matches of woQ's ID column. since
                                     //woQ.ID is the common point of reference for
                                     //like, everything, there should be no nulls.
                   .GroupJoin(zQ, alef => alef.bet.gimel.dalet.workerAssignedID, w => w.ID,
                                 (alef, w) => new
                                {
                                    alef,
                                    listDWC = alef.bet.someValue == 0 ? (w.FirstOrDefault().someID == type1 ? 1 : 0) : 0,
                                    propioDWC = alef.bet.someValue == alef.bet.gimel.dalet.workerAssignedID ? 
                                                    (w.FirstOrDefault().someID == type1 ? 1 : 0) : 0,

                                })  
                                    // here I'm stuck because there's no way to do 
                                    //the future conditions, i.e., what would be my 
                                    //second subquery
                   .Where(x => x.alef.timeOfWork == dateRequested)
                   .GroupBy(y => y.alef.bet.gimel.dalet.ID)
                   .Select(group => new dailyReport
                                {
                                    count1 = group.Sum(z => z.listDWC),
                                    count2 = group.Sum(z => z.propioDWC),
                                    count3 = //???
                                    count4 = //???
                                });

        return query;
    }
//snip class definition below
//剪断上面的注入内容
公共IQueryable DailyCasaLatina(DateTime dateRequested)
{
可查询查询;
var daletQ=waRepo.GetAllQ();
var zQ=zRepo.GetAllQ();
var alefQ=alefRepo.GetAllQ();
var betQ=betRepo.GetAllQ();
var gimelQ=gimelRepo.GetAllQ();
int type1=20;
int type2=21;
query=daletQ
.GroupJoin(gimelQ,dalet=>dalet.skillID,look=>look.ID,
(dalet,看)=>新的
{
达莱,
enSkillText=look.FirstOrDefault().text\u EN
})//当前设想的是
//all.skillID,提供英文文本
//中的列和条件匹配
//接下来的三个连接。
.GroupJoin(betQ,gimel=>gimel.dalet.workOrderID,wr=>wr.workOrderID,
(gimel,wr)=>新
{
吉梅尔,
reqWorkerID=wr.FirstOrDefault().WorkerID,
reqOrderID=wr.FirstOrDefault().WorkOrderID
})//现在设想在原始表上进行联接
//workerID中的任何匹配项被加入的位置。此
//这是个问题,我需要加入两个
//避免重复的条件。
.GroupJoin(alefQ,bet=>bet.gimel.dalet.workOrderID,wo=>wo.ID,
(下注,wo)=>新
{
打赌
工时=wo.FirstOrDefault().dateTimeofWork
})//现在设想另一个连接,其中
//来自woQ的dateTimeofWork属性已盖章
//在woQ的ID列的所有匹配项上。自
//woQ.ID是本项目的共同参考点
//就像,一切,都不应该有空值。
.GroupJoin(zQ,alef=>alef.bet.gimel.dalet.workerAssignedID,w=>w.ID,
(alef,w)=>新
{
阿列夫,
listDWC=alef.bet.someValue==0?(w.FirstOrDefault().someID==type1?1:0):0,
propioDWC=alef.bet.someValue==alef.bet.gimel.dalet.workerAssignedID?
(w.FirstOrDefault().someID==type1?1:0):0,
})  
//我被困在这里,因为没有办法
//未来的条件,即我的
//第二子查询
.Where(x=>x.alef.timeOfWork==dateRequested)
.GroupBy(y=>y.alef.bet.gimel.dalet.ID)
.选择(组=>新建DailReport
{
count1=group.Sum(z=>z.listDWC),
count2=组和(z=>z.propioDWC),
count3=/???
count4=/???
});
返回查询;
}
//剪类定义如下
所以,很抱歉问了这么长的问题(虽然我看得比较长),但是关于如何在这里压缩我的第二个子查询的任何想法都会很有帮助。我对LINQ不太了解,老实说,我不知道是否可以单独放置.Where子句和/或second.Select子句。需要注意的一点是dailyReport是一个已定义的类,并且必须(在我们的示例中)定义count1到count4

谢谢你的帮助


Chaim

根据评论确定,分解此monster sql查询将更有利于其代码的可维护性,如果需要,将创建一个新问题。

根据评论确定,分解此monster sql查询将更有利于其代码的可维护性和新的查询如果需要,问题将被创建。

毫无疑问,人们可以告诉您如何将所有问题都放在一个查询中,但我发现,将其分解成更小的块更具可读性。记住,这样做你不会失去任何东西。在执行类似于
ToList()
的操作或尝试查看数据之前,不会执行LINQ。现在,创建一个一位的var,并在下一个查询中使用它。如果您回到业务需求,因为sql是基于集合的,所以您不得不创建sql语句的怪物,那么您可以更简单地在linq中重新创建相同的结果,并让它们以更易于管理的方式遵循业务规则。尝试一下。当我有更易管理的部分时,我会发布一个编辑。很好,我应该补充一点,虽然你很容易获得更易管理的c