Manipolazione delle query EntityFramework, wrapping del provider db, alberi delle espressioni db

c# entity-framework-4 expression expression-trees localization

Domanda

Sto cercando di implementare la logica di localizzazione dei dati per Entity Framework. Pertanto, se per esempio una query seleziona la proprietà Title , dietro le quinte dovrebbe fare riferimento alla colonna Title_enGB o Title_deCH seconda della cultura dell'utente corrente.

Per raggiungere questo obiettivo, vorrei riscrivere i CommandTrees di DbExpression da Entity Framework. Ho pensato che questi alberi siano un nuovo modo comune di .NET per la creazione di database cross insert / update / select. Ma ora tutti i costruttori / factory rilevanti nei namespace System.Data.Metadata e System.Data.Common.CommandTrees in System.Data.Entity.dll sono interni !! (In msdn documentato come pubblico, come: DbExpressionBuilder ).

Qualcuno ha un'idea per ottenere questa manipolazione della query con o senza la riscrittura dell'albero delle query?

il mio codice desiderato: ( public class DbProviderServicesWrapper : DbProviderServices )

/// <summary>
/// Creates a command definition object for the specified provider manifest and command tree.
/// </summary>
/// <param name="providerManifest">Provider manifest previously retrieved from the store provider.</param>
/// <param name="commandTree">Command tree for the statement.</param>
/// <returns>
/// An exectable command definition object.
/// </returns>
protected override DbCommandDefinition CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree)
{
    var originalCommandTree = commandTree as DbQueryCommandTree;
    if (originalCommandTree != null)
    {
        var expression = new MyCustomQueryRewriter(originalTree.MetadataWorkspace).Visit(originalCommandTree.Query);
        commandTree = DbQueryCommandTree.FromValidExpression(originalCommandTree.MetadataWorkspace, originalCommandTree.DataSpace, expression);
    }

    // TODO: UpdateCommand/InsertCommand

    var inner = this.Inner.CreateCommandDefinition(providerManifest, commandTree);
    var def = new DbCommandDefinitionWrapper(inner, (c, cd) => new DbCommandWrapper(c));

    return def;
}



Aggiornare

Avere due colonne del titolo su un tavolo non è bello ma è più semplice da implementare in un primo passaggio. Più tardi mi unirò ad un'altra tabella con i campi localizzati, quindi la tabella principale conterrà solo dati invarianti.

Multi lingua

Risposta popolare

Sono d'accordo con la risposta di Shiraz che questo non dovrebbe essere quello che vuoi se sei ancora in grado di cambiare il progetto, ma suppongo che si tratti di un'applicazione esistente che stai convertendo in Entity Framework.

Se è così, è importante che le colonne Title_enGB / etc siano mappate nel file EDMX / POCOs. Se lo sono, suppongo sia possibile. Quello che potresti fare qui è utilizzare un visitatore di Expression che visita MemberExpressions, controlla se accedono a una proprietà denominata "Title" (potresti creare una whitelist di proprietà che dovevano essere trattate in questo modo) e quindi restituire una nuova MemberExpression che invece accede Title_enGB se l'utente che ha effettuato l'accesso ha quella lingua impostata.

Un rapido esempio:

public class MemberVisitor : ExpressionVisitor
{
  protected override Expression VisitMember(MemberExpression node)
  {
    if(node.Member.Name == "Title")
    {
        return Expression.Property(node.Expression, "Title_" + User.LanguageCode)
    }

    return base.VisitMember(node);
  }
}

E poi prima di eseguire la query:

var visitor = new MemberVisitor();
visitor.Visit(query);

Ancora una volta, questa è solo una buona idea se non si ha più alcun controllo sul database.

Questa soluzione può essere o meno praticabile per te, a seconda della tua situazione esatta, ma la riscrittura delle query usando Expressions è sicuramente possibile.

È una soluzione di livello molto più elevato rispetto alla modifica di Entity Framework che genera le query SQL effettive. Questo è davvero nascosto da te, probabilmente con una buona ragione. Invece, basta modificare l'albero delle espressioni che descrive la query e lasciare che Entity Framework si preoccupi di convertirlo in SQL.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché