Einen Teil einer IQueryable-Abfrage ausführen und den Rest an Linq for Objects übertragen

c# expression-trees iqueryable linq

Frage

Ich habe einen Linq-Provider, der erfolgreich Daten von meiner gewählten Datenquelle bezieht, aber was ich jetzt tun möchte, dass ich meine gefilterte Ergebnismenge habe, ist Linq zu Objects, um den Rest der Ausdrucksbaumstruktur zu verarbeiten (für Dinge wie Joins, Projektion usw.)

Mein Gedanke war, dass ich die Expression-Konstante, die meinen IQueryProvider enthält, einfach mit den Resultsets IEnumerable über einen ExpressionVisitor ersetzen und dann diesen neuen Ausdruck zurückgeben kann. Gib auch den IEnumerable-Provider von meinem IQueryable zurück ... aber das scheint nicht zu funktionieren :-(

Irgendwelche Ideen?

Edit: Einige gute Antworten hier, aber angesichts der Form ...

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
          }

In meinem Provider kann ich die 2 Resultsets von Kunden und Bestellungen leicht zurückbekommen, wenn die Daten von einer SQL-Quelle stammten, würde ich einfach die SQL-Join-Syntax konstruieren und weiterleiten, aber in diesem Fall stammen die Daten nicht von einer SQL-Quelle Ich muss den Join-Code machen ... aber wie gesagt, ich habe die 2 Ergebnismengen und Linq zu Objects kann einen Join machen ... (und später die Projektion), es wäre wirklich schön, einfach die Expression-Konstanten MyProv.Table<Customer> und MyProv.Table<Order> mit List<Customer> und List<Order> und lassen Sie eine List<> Anbieter den Ausdruck verarbeiten ... ist das möglich? Wie?

Akzeptierte Antwort

Die Sache, nach der ich suchte, war, die Queryable <> -Konstante im Ausdrucksbaum durch eine konkrete IEnumerable (oder IQueryable via .AsQueryable ()) Ergebnismenge zu ersetzen ... das ist ein komplexes Thema, das für Linq wahrscheinlich nur Sinn ergibt Provider Writer, die knietief in den Expressionsbaumbesuchern etc. sind

Ich habe ein Snippet in der msdn Walkthrough gefunden, das so etwas wie das, wonach ich suche, hat, das gibt mir einen Weg nach vorne ...

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

Beliebte Antwort

Beide vorherigen Antworten funktionieren, aber es liest besser, wenn Sie AsEnumerable () verwenden, um das IQueryable zu IEnumerable zu konvertieren:

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

BEARBEITEN:

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



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum