9
votes

Comment intercepter et modifier la requête SQL à Linq à SQL

Je me demandais s'il y a un moyen d'intercepter et de modifier le SQL généré de Linq à SQL avant que la requête soit envoyée?

Fondamentalement, nous avons une couche de sécurité record, qui donnait une requête comme «Sélectionnez * à partir d'enregistrements», il modifiera la requête pour être quelque chose comme «Sélectionner * à partir des enregistrements où [SomesecurityFilter] '

J'essaie de trouver le meilleur moyen d'intercepter et de modifier le SQL avant son exécuté par le fournisseur LINQ vers SQL.


1 commentaires

Existe-t-il une raison spécifique que le filtre doit être mis en œuvre au point LINQ vers SQL génère le SQL? Il serait éventuellement plus simple si les filtres étaient a) mis en œuvre via des vues de votre DB ou B) en modélisant votre modèle d'objet de sécurité dans votre application et en mettant en œuvre les filtres au point que vous définissez vos expressions de requête LINQ?


4 Réponses :


2
votes

La première chose à l'esprit est de modifier la requête et de renvoyer le résultat dans le format non linq xxx

Essayez d'ajouter votre état au SelectCommand et voyez si cela aide.


0 commentaires

1
votes

Essayez de configurer une vue dans la base de données qui applique le filtre de sécurité aux enregistrements au besoin, puis lors de la récupération des enregistrements à travers L2S. Cela garantira que les enregistrements que vous avez besoin ne seront pas retournés.

Alternativement, ajoutez un .illeurs () à la requête avant d'être soumis qui appliquera le filtre de sécurité. Cela vous permettra d'appliquer le filtre par programme (au cas où il doit être modifié en fonction du scénario).


0 commentaires

3
votes

OK, d'abord pour répondre directement à votre question (mais lisez-le pour des mots de prudence;)), il y a un moyen, bien qu'un point finie, de faire ce que vous voulez.

static class MySecurityExtensions
{
    public static IQueryable<Customer> ApplySecurity(this IQueryable<Customer> source)
    {
        return source.Where(x => x.MiddleName == "M.");
    }
} 

//...
// now apply it to any Customer query
var cs = (from c in db.Customers select c).ApplySecurity();


2 commentaires

Y a-t-il de toute façon pour forcer LINQ à appliquer la "liste de rechange" lorsque l'extension de toutes les requêtes avant de les exécuter automatiquement - de sorte que le point de vue du développeur, ils écrivaient: var cs = (de C dans db.customers Select c); Mais avant que la requête ne frappe la dB, elle applique la sécurité où la clause?


Pas à ma connaissance, le code du bâtiment des arbres est généré au moment de la compilation.



2
votes

Si vous souhaitez intercepter le SQL généré par L2S et le violon, votre meilleure option consiste à créer une classe d'emballage pour SQLConnection, SQLCommand, DBProviderFactory, etc. Donnez une instance emballée de SQLConnection à la surcharge du constructeur L2S DataContext qui prend un Connexion DB. Dans la connexion emballée, vous pouvez remplacer le DBProviderFactory avec votre propre classe dérivée DBProviderFactory personnalisée qui renvoie des versions enveloppées de SQLCOMMAND, etc.

par exemple: xxx

lorsque vous utilisez: xxx

qui dit, vous vraiment veux descendre cette route? Vous devrez être capable d'analyser les instructions et les requêtes SQL générées par L2S afin de les modifier correctement. Si vous pouvez plutôt modifier les requêtes LINQ pour ajouter tout ce que vous souhaitez les ajouter, c'est probablement une meilleure alternative.

N'oubliez pas que les requêtes LINQ sont composables, vous pouvez donc ajouter des «extras» dans une méthode distincte. Si vous avez quelque chose que vous souhaitez ajouter à de nombreuses questions.


5 commentaires

C'est la route que j'ai descendue. Heureusement, nous avons déjà un analyseur SQL à la main!


@mrwayne J'espérais que vous vous présenteriez de choisir la réponse que vous vouliez. Merci d'avoir pris la décision difficile pour moi; o)


Comment avez-vous réussi à hériter de SQLConnection quand il est scellé? La classe ne compilera pas comme ça.


Downvoted, car vous ne pouvez pas hériter de SQLConnection (et que le DataContext n'acceptera pas d'être construit avec une idbconnection comme apparemment, il tentera de la jeter à SQLConnection en interne). Faites-moi savoir si je me trompe cependant.


@mrwayne en utilisant toujours ceci? Vous avez un code d'exemple pour savoir comment prolonger SQLConnection lorsqu'il est scellé?