Bagaimana cara menulis kueri Linq ke NHibernate ini

Kami memiliki entitas seperti ini:

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

Saya ingin menulis pertanyaan ini:

    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

Untuk beberapa alasan saya ingin menggunakan Linq To Nhibernate (Kami memiliki mekanisme pemfilteran kompleks yang menghasilkan Expression<Func<File,bool>>)

Sejauh ini saya tidak dapat menemukan cara untuk mencapai hal ini menggunakan Linq To NHibernate. Inilah beberapa upaya saya:

Jumlah Kondisi: (Tidak terkecuali tetapi tetap menghitung semua baris)

    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)
    });

Jumlah Kondisi : Tidak Didukung/Pengecualian yang Diimplementasikan

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)
});

SELECT Sebelum GROUP : Tidak Didukung/Pengecualian yang Diimplementasikan

    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 : Tidak Didukung/Diimplementasikan Pengecualian

    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)
});

Saya tidak punya petunjuk lain. Ada ide lain?


person Beatles1692    schedule 28.04.2015    source sumber


Jawaban (2)


Saya menggunakan upaya kedua Anda dan memasukkan ToList() sebelum Select(). Hasilnya akan terlihat seperti ini:

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)
});

Dengan cara ini Select diterapkan ke Daftar, bukan IQueryable.

person Florian Lim    schedule 28.04.2015
comment
Itu bisa menjadi alternatif jika saya tidak dapat menemukan cara untuk membuat kueri saya dengan cara lain :) terima kasih - person Beatles1692; 28.04.2015
comment
Oke, saya mengujinya dan ternyata ide yang sangat buruk karena tidak memungkinkan Anda memproyeksikan satu-satunya kolom yang Anda perlukan sebelum GroupBy dan dengan demikian ia akan mencoba mengambil semua grafik objek apakah mereka tidak malas dimuat dan dalam kasus kami itu menghasilkan SELECT N+1 :) - person Beatles1692; 28.04.2015

Saya tidak tahu apakah Anda bisa menerapkannya dengan Linq ke NH. Apakah Anda dapat menggunakan QueryOver saja? API QueryOver juga menggunakan Expression<Func<T,bool>> di klausa Where sehingga Anda dapat membuatnya berfungsi seperti ini dengan filter yang ada:

            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 tidak benar-benar berfungsi dengan tipe anonim sehingga Anda harus mendefinisikan MyDto dengan properti yang ingin Anda kembalikan, yaitu Region, ShowCount dan NotShowCount

person BunkerMentality    schedule 28.04.2015
comment
Sayangnya seperti yang saya sebutkan dalam pertanyaan saya, saya khawatir harus menggunakan Linq untuk NHibernate. - person Beatles1692; 28.04.2015
comment
@ Beatles1692 Oke maaf soal itu, saya pikir Anda hanya ingin menggunakan Linq ke Nh karena Anda ingin menggunakan kembali mekanisme pemfilteran yang mengembalikan Expression<Func<File,bool>> - person BunkerMentality; 28.04.2015
comment
Masalahnya adalah QueryOver tidak mendukung beberapa Linq expressions seperti Any - person Beatles1692; 28.04.2015
comment
Ada beberapa cara untuk membuat metode ekstensi Anda sendiri untuk penyedia nhibernate linq. Coba lihat ini mungkin: codeproject .com/Articles/318177/ dan mungkin mencoba membuat ekstensi Anda sendiri, yaitu SumWhere(x=›x.ShowLocation==1) atau semacamnya. Saya belum pernah mencobanya tetapi mungkin patut dicoba? - person BunkerMentality; 28.04.2015