EntityFramework-Abfrage-Manipulation, db-Provider-Wrapping, db-Ausdrucksstrukturen

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

Frage

Ich versuche, Datenlokalisierungslogik für Entity Framework zu implementieren. Wenn beispielsweise eine Abfrage die Title Eigenschaft auswählt, sollte sie im Title_enGB auf die Spalte Title_enGB oder Title_deCH Abhängigkeit von der aktuellen Benutzerkultur Title_deCH .

Um dies zu erreichen, möchte ich die DbExpression CommandTrees von Entity Framework neu schreiben. Ich dachte, diese Bäume sind eine neue gängige .NET-Methode zum System.Data.Common.CommandTrees von System.Data.Entity.dll Datenbankeinfügungs- / Aktualisierungs- / Auswahlabfragen. Nun aber alle relevanten Konstruktoren / Fabriken in den Namespaces System.Data.Metadata und System.Data.Common.CommandTrees in System.Data.Entity.dll sind intern !! (In msdn dokumentiert als public, wie: DbExpressionBuilder ).

Hat jemand eine Idee, um diese Abfrage-Manipulation mit oder ohne Query Tree Neuschreiben zu erreichen?

mein gewünschter Code: ( 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;
}



Aktualisieren

Es ist nicht cool, zwei Titelspalten auf einer Tabelle zu haben, aber es ist einfacher, sie in einem ersten Schritt zu implementieren. Später schließe ich mich einer anderen Tabelle mit den lokalisierten Feldern an, sodass die Haupttabelle nur invariante Daten enthält.

Mehrsprachig

Beliebte Antwort

Ich stimme der Antwort von Shiraz zu, dass dies nicht das sein soll, was Sie wollen, wenn Sie immer noch in der Lage sind, das Design zu ändern, aber ich nehme an, dass dies eine vorhandene Anwendung ist, die Sie in Entity Framework konvertieren.

Wenn dies der Fall ist, spielt es eine Rolle, ob die Title_enGB / etc-Spalten in der EDMX-Datei / den POCOs zugeordnet sind. Wenn ja, ist das möglich. Was Sie hier tun könnten, ist ein Expression-Besucher, der MemberExpressions besucht, prüft, ob er auf eine Eigenschaft namens "Title" zugreift (Sie könnten eine Whitelist von Eigenschaften erstellen, die so behandelt werden müssen) und dann eine neue MemberExpression zurückgeben, die stattdessen auf Zugriffe zugreift Title_enGB, wenn der angemeldete Benutzer diese Sprache eingestellt hat.

Ein kurzes Beispiel:

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

Und bevor Sie die Abfrage ausführen:

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

Auch dies ist nur eine gute Idee, wenn Sie die Datenbank nicht mehr kontrollieren können.

Diese Lösung ist möglicherweise für Sie praktisch oder nicht, abhängig von Ihrer genauen Situation, aber das Umschreiben von Abfragen mit Expressions ist definitiv möglich.

Es ist eine Lösung auf höherer Ebene, als zu ändern, wie Entity Framework die eigentlichen SQL-Abfragen generiert. Das ist in der Tat vor Ihnen verborgen, wahrscheinlich aus gutem Grund. Stattdessen ändern Sie einfach den Ausdrucksbaum, der die Abfrage beschreibt, und lassen Entity Framework sich sorgen, dass es in SQL konvertiert wird.



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