أداء جزء من الاستعلام IQueryable وتأجيل الباقي لينق لكائنات

StackOverflow https://stackoverflow.com/questions/695678

سؤال

ولدي مزود ينق أن يذهب بنجاح ويحصل على بيانات من مصدر بيانات مختاري، ولكن ما أود القيام به الآن أن لدي resultset وتصفيتها، هو السماح LINQ إلى كائنات لمعالجة ما تبقى من شجرة التعبير (لأشياء كما ينضم، والإسقاط وغيرها)

وكان فكرتي بأنني يمكن أن تحل محل فقط ثابت التعبير الذي يحتوي IQueryProvider بلدي بالنتيجة مجموعات IEnumerable عبر ExpressionVisitor ثم يعود هذا التعبير الجديد. كما يمكن الرجوع موفر IEnumerable من بلدي IQueryable ... ولكن هذا لا يبدو للعمل: - (

وأي فكرة ل؟

وتحرير: بعض الإجابات جيدة هنا، ولكن نظرا للشكل ...

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
          }

في مزود لي يمكنني الحصول بسهولة إلى الخلف 2 resultsets من العملاء وأوامر، إذا كانت البيانات من مصدر SQL أود أن بناء عادل وتمر على SQL تاريخ لغوي، ولكن هذه الحالة البيانات ليست من SQL المصدر بحيث يجب أن أفعل الصلة في التعليمات البرمجية ... ولكن كما قلت لدي مجموعات النتائج 2، وينق إلى كائنات يمكن القيام انضمام ... (وفيما بعد الإسقاط) أنه سيكون من الرائع الحقيقي لتحل محل فقط الثوابت التعبير MyProv.Table<Customer> وMyProv.Table<Order> مع List<Customer> وList<Order> وتتيح عملية مزود List<> التعبير ... هل ذلك ممكن؟ كيف؟

هل كانت مفيدة؟

المحلول 2

وهذا النوع من الشيء الذي كنت بعد استبدال Queryable <> المستمر في شجرة التعبير مع الخرسانة IEnumerable (أو IQueryable عبر .AsQueryable ()) مجموعة النتائج ... هذا هو موضوع معقد ربما فقط يجعل أي بمعنى أن الكتاب مزود ينق الذين هم في الركبة في عمق زوار شجرة التعبير وما إلى ذلك.

ولقد وجدت قصاصة على تجول MSDN أن يفعل شيئا مثل ما أنا بعد، وهذا يعطيني طريقة للمضي قدما ...

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

نصائح أخرى

وكل الإجابات السابقة العمل، ولكنه يقرأ أفضل إذا كنت تستخدم AsEnumerable () ليلقي IQueryable إلى IEnumerable:

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

وتحرير:

// ... 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

إذا نفذت خطة مستودع هل يمكن أن تفلت من مجرد توفير IQueryable ذهابا ومجردة بعيدا عن الطاولة.

مثال:

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
          }

وبعد ذلك فقط بناء مزود لنموذج لنمط IQueryable في طريقة مستودع تماما مثل <وأ href = "http://iridescence.no/post/Linq-to-Sql-Programming-Against-an-Interface-and -The-مستودع-Pattern.aspx "يختلط =" نوفولو noreferrer "> توضح هذه المقالة .

وبهذه الطريقة، يمكنك كتابة جميع أنواع مقدمي الخدمات لاستخدامها في كل ما تحتاجه. هل يمكن أن يكون مزود SQL LINQ 2، أو كتابة في مزود الذاكرة للاختبارات وحدتك.

وهذه الطريقة مستودع لموفر LINQ 2 SQL أن ننظر بشيء من هذا القبيل:

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

وإذا لم أنا سوء الفهم، عموما أنا مجرد إضافة .ToArray () في سلسلة من أساليب LINQ عند النقطة التي أريد مزود LINQ إلى تنفيذ.

وعلى سبيل المثال (اعتقد LINQ إلى SQL)

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

وهكذا من خلال OrderBy () يحصل على ترجمتها إلى SQL، ولكن تحديد () لا LINQ إلى كائنات.

والجواب روب هو جيد، ولكن تجبر التعداد الكامل. هل يمكن أن يلقي للحفاظ على جملة أسلوب الإرشاد والتقييم كسول:

var res = ((IEnumerable<Foo>)dc.Foos
            .Where(x => x.Bla > 0))  // IQueryable
          .Where(y => y.Snag > 0)   // IEnumerable
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top