LINQ-to entities jenerik == geçici çözüm

Aşağıdaki LINQ varlıktan sorgum var

IQueryable> GetFirstOperationsForEveryId
    (IQueryable> ItemHistory)
{
    var q = (from h in ItemHistory
             where h.OperationId ==
                (from h1 in ItemHistory
                 where h1.GenericId == h.GenericId
                 select h1.OperationId).Min()
             select h);
    return q;
}

ItemHistory is a generic query. It can be obtained in the following way

var history1 = MyEntitiySet1.Select(obj =>
    new History{ obj.OperationId, GenericId = obj.LongId });
var history2 = AnotherEntitiySet.Select(obj =>
    new History{ obj.OperationId, GenericId = obj.StringId });

In the end of all I want a generic query being able to work with any entity collection convertible to History.

Sorun, kod iç sorgudaki GenericId karşılaştırması nedeniyle derleme 'dir (İşletmen' == ',' T 've' T 'tiplerine işlenemez).

== 'dan h1.GenericId.Equals (h.GenericId) ' i değiştirirsem aşağıdaki NotSupportedException değerini alırım:

'System.Object' yazmak için 'System.Int64' türünü çeviremedi. LINQ to Tüzel Kişiler, yalnızca Varlık Veri Modeli ilkel türlerini yayınlamayı destekler.

Alt sorgu yerine gruplama yapmayı ve sonuçlara katılmayı denedim.

IQueryable> GetFirstOperationsForEveryId
    (IQueryable> ItemHistory)
{
    var grouped = (from h1 in ItemHistory
                   group h1 by h1.GenericId into tt
                   select new
                   {
                        GenericId = tt.Key,
                        OperationId = tt.Min(ttt => ttt.OperationId)
                   });

    var q = (from h in ItemHistory
             join g in grouped
                on new { h.OperationId, h.GenericId }
                equals new { g.OperationId, g.GenericId }
             select h);
    return q;
}

GenericId'ler equals anahtar sözcüğü ile karşılaştırıldıkları için çalışmaktadır, ancak gerçek verilerle yapılan sorgu çok yavaştır (adanmış postgresql sunucusunda 11 saat çalışmaktadır).

Dışardaki deyim için bir bütün ifade oluşturma seçeneği vardır. Ama kod çok uzun ve belirsiz olurdu.

LINQ-to varlıklar içindeki jeneriklerle eşitlik karşılaştırması için basit bir çözüm var mı?

2

4 cevap

Bunu deneyin, ekstra sorgu/katılmadan istediğinizi gerçekleştirmesi gerektiğini düşünüyorum

IQueryable> GetFirstOperationsForEveryId
    (IQueryable> ItemHistory)
{
  var q = from h in ItemHistory
          group h by h.GenericId into tt
          let first = (from t in tt
                        orderby t.GenericId
                        select t).FirstOrDefault()
          select first;

  return q;
}
1
katma
Oldukça zarif bir çözüm! Ancak maalesef Npgsql'de henüz uygulanmadı (2.0.11.92 itibariyle). System.Data.EntityCommandCompilationException: Komut tanımını hazırlarken bir hata oluştu. ---> System.NotImplementedException: Yöntem veya işlem uygulanmadı. Asıl sorun, dizin oluşturmayı unuttuğumdur. Grup + katılma sorgusu 11 saat çalıştı neden budur. Endekslerle oldukça hızlı çalışır.
katma yazar Mike, kaynak

Ayrıca, GenericId ve OperationId özelliğini uygulayan IItemHistory bir inteface için T üzerinde genel bir kısıtlama da ayarlayabilirsiniz.

0
katma

Benim sorum zaten bir çözüm içeriyor. Grup + birleştirmeyle ikinci yöntem, tablo düzgün şekilde dizine eklendiğinde iyi çalışır. Veritabanı tablosundan 370k satır almak 3.28 saniyedir. Aslında, jenerik olmayan varyantta ilk sorgu, ikinci olandan postgresql'de daha yavaştır. 26.68 vs vs 4.75.

0
katma
IQueryable> GetFirstOperationsForEveryId
(IQueryable> ItemHistory)
{
var grouped = (from h1 in ItemHistory
               group t by h1.GenericId into tt
               select new
               {
                    GenericId = tt.Key,
                    OperationId = tt.Min(ttt => ttt.OperationId)
               });

var q = (from h in ItemHistory
         join g in grouped
            on new { h.OperationId, h.GenericId }
            equals new { g.OperationId, g.GenericId }
         select h);
return q;
}
0
katma
Yayınladığımdan farkı nedir?
katma yazar Mike, kaynak