วิธีเขียนแบบสอบถาม Linq นี้ไปยัง NHibernate

เรามีเอนทิตีเช่นนี้:

public class File{
       public int Region{get;set;}
       public bool ShowLocation{get;set;}
       //Other fields are omitted
}

ฉันต้องการเขียนแบบสอบถามนี้:

    SELECT Region,SUM(CASE WHEN ShowLocation=1 THEN 1 ELSE 0 END) AS
 ShowCount,SUM(CASE WHEN ShowLocation=0 THEN 1 ELSE 0 END) AS NotShowCount
--WHERE omitted for the sake of simplicity
GROUP BY Region

ด้วยเหตุผลบางอย่าง ฉันต้องการใช้ Linq To Nhibernate (เรามีกลไกการกรองที่ซับซ้อนที่สร้าง Expression<Func<File,bool>>)

จนถึงตอนนี้ฉันไม่พบวิธีใดในการบรรลุเป้าหมายนี้โดยใช้ Linq To NHibernate นี่คือความพยายามบางส่วนของฉัน:

Conditioanl Count:(ไม่มีข้อยกเว้น แต่จะนับทุกแถวอยู่แล้ว)

    Files
    .Where(whereExpression)
    .GroupBy(x=>x.Region)
    .Select(x=>new
    {
        x.Region,
        ShowCount=x.Count(f=>f.ShowLocation==1),
        NotShowCount=x.Count(f=>f.ShowLocation==0)
    });

ผลรวมตามเงื่อนไข: ไม่รองรับ/ยกเว้นการใช้งาน

Files
.Where(whereExpression)
.GroupBy(x=>x.Region)
.Select(x=>new 
{
  x.Region,
  ShowCount=x.SUM(f=>f.ShowLocation==1?1:0),
  NotShowCount=x.SUM(f=>f.ShowLocation==0?1:0)
});

เลือกก่อนกลุ่ม: ไม่รองรับ/ยกเว้นการใช้งาน

    Files.Where(whereExpression).Select(x=>new
    {
       x.Region,
       Show=x.ShowLocation==1?1:0,
       NotShow=x.ShowLocation==0?1:0
    })
    .GroupBy(x=>x.Region)
    .Select(x=>new 
    {
       x.Region,
       ShowCount=x.SUM(f=>f.Show),
       NotShowCount=x.SUM(f=>f.NotShow)
    });

UNION : ไม่รองรับ/ยกเว้นการใช้งาน

    Files
       .Where(whereExpression)
       .Where(x=>x.ShowLocation==1)
 .Select(x=>new
{
x.Region,
Show=1,NotShow=0
})
.Union(Files
 .Where(whereExpression)
.Where(x=>x.ShowLocation==0)
.Select(x=>new
{x.Region,
Show=0,
NotShow=1
}))
.GroupBy(x=>x.Region)
.Select(x=>new 
{
x.Region,
CountShow=x.Count(a=>a.Show),
CountNotShow=x.Count(a=>a.NotShow)
});

ฉันไม่มีเบาะแสอื่น ๆ มีความคิดอื่นอีกไหม?


person Beatles1692    schedule 28.04.2015    source แหล่งที่มา


คำตอบ (2)


ฉันใช้ความพยายามครั้งที่สองของคุณและแทรก ToList() ก่อน Select() ผลลัพธ์จะมีลักษณะดังนี้:

Files
.Where(whereExpression)
.GroupBy(x=>x.Region)
.ToList<IGrouping<int, File>>()
.Select(x=>new 
{
  x.Key,
  ShowCount = x.Sum(f => f.ShowLocation == 1 ? 1 : 0),
  NotShowCount = x.Sum(f => f.ShowLocation == 0 ? 1 : 0)
});

ด้วยวิธีนี้ Select จะถูกนำไปใช้กับรายการแทน IQueryable

person Florian Lim    schedule 28.04.2015
comment
นั่นอาจเป็นอีกทางเลือกหนึ่งหากฉันไม่สามารถหาวิธีสร้างแบบสอบถามด้วยวิธีอื่นได้ :) ขอบคุณ - person Beatles1692; 28.04.2015
comment
โอเค ฉันทดสอบแล้ว และกลายเป็นความคิดที่แย่มาก เพราะมันไม่อนุญาตให้คุณฉายภาพคอลัมน์เดียวที่คุณต้องการก่อน GroupBy ดังนั้นมันจะพยายามดึงกราฟวัตถุทั้งหมดไม่ว่ากราฟเหล่านั้นจะไม่ได้โหลดแบบขี้เกียจก็ตาม และในกรณีของเรา มันส่งผลให้ SELECT N+1 :) - person Beatles1692; 28.04.2015

ฉันไม่รู้ว่าคุณจะสามารถใช้งาน Linq กับ NH ได้หรือไม่ คุณสามารถใช้ QueryOver แทนได้หรือไม่? QueryOver API ยังใช้ Expression<Func<T,bool>> ในส่วนคำสั่งด้วย ดังนั้นคุณควรจะสามารถทำให้มันทำงานเช่นนี้กับตัวกรองที่มีอยู่ของคุณ:

            MyDto dto = null;

            var myDtoList = session.QueryOver<File>()
                .Select(
                    Projections.Group<File>(x => x.Region).WithAlias(() => dto.Region),
                    Projections.Sum(
                        Projections.Conditional(
                            Restrictions.Where<File>(c => c.ShowLocation== 1),
                            Projections.Constant(1),
                            Projections.Constant(0))).WithAlias(() => dto.ShowCount),
                    Projections.Sum(
                        Projections.Conditional(
                            Restrictions.Where<File>(c => c.ShowLocation== 0),
                            Projections.Constant(1),
                            Projections.Constant(0))).WithAlias(() => dto.NotShowCount))
                .TransformUsing(Transformers.AliasToBean<MyDto>())
                .List<MyDto>();

QueryOver ใช้งานไม่ได้กับประเภทที่ไม่ระบุชื่อ ดังนั้นคุณจะต้องกำหนด MyDto ด้วยคุณสมบัติที่คุณต้องการส่งคืน เช่น Region, ShowCount และ NotShowCount

person BunkerMentality    schedule 28.04.2015
comment
น่าเสียดายที่ดังที่ฉันพูดถึงในคำถามของฉัน ฉันกลัวว่าต้องใช้ Linq เพื่อ NHibernate - person Beatles1692; 28.04.2015
comment
@ Beatles1692 โอเค ขอโทษด้วย ฉันคิดว่าคุณเพียงต้องการใช้ Linq กับ Nh เพราะคุณต้องการใช้กลไกการกรองของคุณที่ส่งคืน Expression<Func<File,bool>> ซ้ำ - person BunkerMentality; 28.04.2015
comment
ปัญหาคือ QueryOver ไม่รองรับ Linq expressions บางส่วน เช่น Any - person Beatles1692; 28.04.2015
comment
มีวิธีการสร้างวิธีการขยายของคุณเองสำหรับผู้ให้บริการ nhibernate linq ลองดูที่นี้: codeproject .com/Articles/318177/ และอาจลองสร้างส่วนขยายของคุณเอง เช่น SumWhere(x=›x.ShowLocation==1) หรืออะไรทำนองนั้น ฉันไม่เคยลองแต่มันอาจจะคุ้มค่าที่จะลอง? - person BunkerMentality; 28.04.2015