2009-03-30 9 views
7

Seçilmiş veri kaynağımdan başarılı bir şekilde veri alıp veri alan bir Linq sağlayıcım var, ancak filtrelenmiş sonuç kümemde sahip olduğum şeyi şimdi yapmak istiyorum. Ekspresyon ağacının geri kalanını işlemek için Nesneler (Katmanlar, yansıtma vb. Gibi şeyler için)IQueryable sorgusunun bir parçasını gerçekleştirme ve geri kalanını Nesneler için Linq'e erteleme

Benim düşüncem, IQueryProvider'ım içeren bir ifade sabitini, bir ExpressionVisitor ile IEnumerable sonuç kümeleriyle değiştirebiliyordum ve yeni ifadeyi döndür. Ayrıca benim IQueryable gelen IEnumerable en sağlayıcı dönmek ... ama bu

Herhangi fikrin

Düzenleme :-(çalışmak görünmüyor:? ... formu verilmiş burada Bazı iyi cevaplar, ama

var qry = from c in MyProv.Table<Customer>() 
      Join o in MyProv.Table<Order>() on c.OrderID equals o.ID 
      select new 
      { 
      CustID = c.ID, 
      OrderID = o.ID 
      } 

Sağlayıcımda, Müşteriler ve Siparişler'deki 2 sonuç kümesini kolayca geri alabilirim, eğer veri bir SQL kaynağından geldiyse, sadece SQL Join sözdizimini yapılandırabilir ve geçirebilirdim, ancak bu durum verilerden değil. SQL kaynağı bu yüzden kodda birleştirme yapmam gerekiyor ... ama 2 sonuç kümesine sahip olduğumu söylediğim gibi, ve Linq to Objects birleştirme yapabilir ... (ve sonrasında izdüşüm) MyProv.Table<Customer> ve MyProv.Table<Order> ve ile MyProv.Table<Order> ve List<Order> yerine İfade sabitlerini ve List<> sağlayıcının ifade işlemine izin vermesi çok güzel olurdu ... bu mümkün mü? Nasıl?

cevap

3

Ben sonra queryable < değiştirilmesi edildi tür bir şey> ifadesi ağacında sabit bir beton IEnumerable (veya IQueryable aracılığıyla ile .AsQueryable()) sonuç kümesi ... Bu, muhtemelen sadece ağaç ziyaretçi vb. Derinlerde diz olan Linq Sağlayıcı yazarlarına herhangi bir anlam ifade eden karmaşık bir konudur.

Bir şey yapan msdn adımında bir pasaj buldum Eğer sadece uzak sırt ve soyut tablo bir IQueryable sağlayarak birlikte kaçmak bir Depo Desen uygulanırsa ben sonra neysem gibi bu bana bir çıkış yolu ...

using System; 
using System.Linq; 
using System.Linq.Expressions; 

namespace LinqToTerraServerProvider 
{ 
    internal class ExpressionTreeModifier : ExpressionVisitor 
    { 
     private IQueryable<Place> queryablePlaces; 

     internal ExpressionTreeModifier(IQueryable<Place> places) 
     { 
      this.queryablePlaces = places; 
     } 

     internal Expression CopyAndModify(Expression expression) 
     { 
      return this.Visit(expression); 
     } 

     protected override Expression VisitConstant(ConstantExpression c) 
     { 
      // Replace the constant QueryableTerraServerData arg with the queryable Place collection. 
      if (c.Type == typeof(QueryableTerraServerData<Place>)) 
       return Expression.Constant(this.queryablePlaces); 
      else 
       return c; 
     } 
    } 
} 
+0

dizlerimin teşekkür ederim - Derin ifade ağacı ziyaretçilerin. :) Bu tam olarak ihtiyacım olan şey – Rik

1

Yanlış anlaşılmadıkça, linq sağlayıcısının yürütmesini istediğim noktada linq yöntemlerinin zincirine genellikle .ToArray() ekledim.

Örneğin) Böylece OrderBy aracılığıyla

var result = datacontext.Table 
    .Where(x => x.Prop == val) 
    .OrderBy(x => x.Prop2) 
    .ToArray() 
    .Select(x => new {CoolProperty = x.Prop, OtherProperty = x.Prop2}); 

((SQL Linq to düşünüyorum) SQL tercüme alır, ancak Seç() Nesneler LINQ olduğunu.

0

Rob'un cevabı iyidir, ancak tam numaralandırmaya zorlar. Eğer AsEnumerable kullanırsanız() IEnumerable IQueryable döküm önceki cevapların Hem çalışmak

var res = ((IEnumerable<Foo>)dc.Foos 
      .Where(x => x.Bla > 0)) // IQueryable 
      .Where(y => y.Snag > 0) // IEnumerable 
5

, ama daha iyi okur:

// Using Bob's code... 
var result = datacontext.Table 
    .Where(x => x.Prop == val) 
    .OrderBy(x => x.Prop2) 
    .AsEnumerable() // <---- anything after this is done by LINQ to Objects 
    .Select(x => new { CoolProperty = x.Prop, OtherProperty = x.Prop2 }); 

Sen uzatma yöntemi sözdizimi ve tembel değerlendirme tutmak için döküm olabilir DÜZENLEME:

// ... or MichaelGG's 
var res = dc.Foos 
      .Where(x => x.Bla > 0) // uses IQueryable provider 
      .AsEnumerable() 
      .Where(y => y.Snag > 0); // IEnumerable, uses LINQ to Objects 
1

verir.

Örnek:

var qry = from c in MyProv.Repository<Customer>() 
      Join o in MyProv.Repository<Order>() on c.OrderID equals o.ID 
      select new 
      { 
      CustID = c.ID, 
      OrderID = o.ID 
      } 

ve sadece this article göstermektedir tıpkı senin Depo yönteminde IQueryable desen modellemek için sağlayıcı kurmak.

Bu sayede, ihtiyacınız olan her şeyi kullanabilmek için her türlü sağlayıcıyı yazabilirsiniz. Bir LINQ 2 SQL sağlayıcınız olabilir veya birim testleriniz için bir bellek sağlayıcıya yazabilirsiniz.

LINQ 2 SQL sağlayıcısı için Depo yöntem şöyle görünecektir:

public IQueryable<T> Repository<T>() where T : class 
{ 
    ITable table = _context.GetTable(typeof(T)); 
    return table.Cast<T>(); 
} 
+0

Çok ilginç, bu hafta sonu bununla oynayacağım. –

İlgili konular