Manipulation de requête EntityFramework, wrapping du fournisseur de base de données, arbres d'expression de base de données

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

Question

J'essaie d'implémenter la logique de localisation des données pour Entity Framework. Ainsi, si par exemple une requête sélectionne la propriété Title , en coulisse, elle doit référencer la colonne Title_enGB ou Title_deCH fonction de la culture de l'utilisateur actuel.

Pour ce faire, j'aimerais réécrire les CommandTrees DbExpression à partir de Entity Framework. Je pensais que ces arbres sont une nouvelle façon de .NET commune pour la construction d' insertion / base de données mise à jour croisée / requêtes SELECT .. Mais maintenant tous les constructeurs / usines concernées dans les espaces de noms System.Data.Metadata et System.Data.Common.CommandTrees dans System.Data.Entity.dll sont internes !! (Dans msdn documenté comme public, comme: DbExpressionBuilder ).

Quelqu'un at-il une idée pour réaliser cette manipulation de requête avec ou sans réécriture d'arborescence de requête?

mon code désiré: ( 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;
}



Mettre à jour

Avoir deux colonnes de titre sur une table n'est pas cool, mais il est plus facile de l'implémenter dans un premier temps. Plus tard, je joindrai une autre table avec les champs localisés, de sorte que la table principale ne contiendra que des données invariantes.

Multilingue

Réponse populaire

Je conviens avec la réponse de Shiraz que cela ne devrait pas être ce que vous voulez si vous êtes toujours capable de modifier la conception, mais je supposerai qu'il s'agit d'une application existante que vous convertissez en Entity Framework.

Si tel est le cas, il importe que les colonnes Title_enGB / etc soient mappées dans le fichier EDMX / POCOs. S'ils le sont, je suppose que c'est possible. Ce que vous pouvez faire ici, c'est utiliser un visiteur Expression qui visite MemberExpressions, vérifie s'il accède à une propriété nommée "Titre" (vous pouvez créer une liste blanche de propriétés devant être traitées de la sorte), puis renvoyer une nouvelle MemberExpression à la place des accès Title_enGB si l'utilisateur connecté a cette langue définie.

Un exemple rapide:

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

Et puis avant d'exécuter la requête:

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

Encore une fois, ce n’est une bonne idée que si vous n’avez plus aucun contrôle sur la base de données.

Cette solution peut être ou ne pas être pratique pour vous, selon votre situation exacte, mais la réécriture de requêtes à l'aide d'Expressions est certainement possible.

C'est une solution de niveau beaucoup plus élevé que de modifier la façon dont Entity Framework génère les requêtes SQL réelles. C'est en effet caché de toi, probablement avec une bonne raison. Au lieu de cela, vous ne faites que modifier l’arbre d’expression qui décrit la requête et laisser Entity Framework s’inquiéter de la conversion en SQL.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi