2009-02-26 8 views
1

Contexte:audit LINQ utilisateur actuel avec l'application web

J'ai une application Web pour laquelle je dois faire l'audit de base de données pour insérer/supprime/mises à jour (et lit peut-être). J'utilise LINQ comme mon ORM. En utilisant quelques idées que j'ai trouvées sur le web, j'ai trouvé une façon d'utiliser des attributs pour décorer mes entités qui ont des tables d'audit associées. La table d'audit elle-même doit inclure les mêmes colonnes avec les mêmes types que la table d'origine en plus des champs pour l'ID et le nom de l'utilisateur actuel, le type de modification, l'heure de modification et si l'opération a réussi. L'audit a lieu au cours de SubmitChanges - mon contexte de données est abstrait et j'hérite et substitue SubmitChanges dans ma mise en œuvre concrète. Le contexte de données abstraites provient en fait d'un AbstractAuditableDataContext qui étend DataContext et ajoute une propriété CurrentUser avec des espaces réservés pour l'ID et le nom d'utilisateur en cours. Par défaut, ils sont 0 et "système" pour les instances où il n'y a pas d'utilisateur connecté - disons lors de l'enregistrement ou de la connexion lorsque certains champs de la table utilisateur peuvent être mis à jour. L'application est écrite en C# en utilisant ASP.NET MVC.

Problème:

Quelle est la meilleure façon de remplir la propriété de l'utilisateur actuel de mon contexte de données dérivées? Dois-je créer une classe utilitaire qui est injectée dans AuditUtility qui vérifie si CurrentUser a été définie et, sinon, la remplit. Pour tester, je me moquerais de ça, mais dans l'application live, il utiliserait probablement paresseux -loading et get/set dans la session. Ou devrais-je modifier la fabrique de contexte de données (utilisée par tous les contrôleurs) pour exécuter cette fonctionnalité. J'utilise déjà une fausse usine lors des tests unitaires, donc cela n'implique pas la création de nouvelles classes. Ou la dérivation doit-elle être effectuée en dehors de l'usine et l'utilisateur actuel doit-il être injecté lors de la création du contexte. Cela me permettrait de faire «au nom de» l'audit. Je me rends compte que c'est quelque peu subjectif, mais j'apprécierais toutes les pensées/expériences que vous pourriez contribuer.

Merci.

Répondre

0

J'ai fini par créer une classe CurrentUserUtilityBase qui a une méthode GetAuditUser qui prend le contexte de données actuel et récupère l'objet utilisateur qui correspond au nom d'utilisateur actuel dans HttpContext.User.Identity. Il utilise cet objet pour extraire l'identifiant et le nom d'affichage de l'utilisateur actuel et créer et retourner un objet AuditUser contenant ces propriétés.

Ma classe d'implémentation utilise une fabrique pour obtenir une instance de mon contexte de données et appelle la méthode de classe de base sur ce contexte de données. Les méthodes d'usine pour mon contexte de données utilisent l'utilitaire utilisateur actuel pour injecter l'utilisateur actuel pour le contexte dans le contexte après sa création.

0

Quelle est la portée de votre DataContext (Application, Session, Request, per BusinessObject ..)? Si cela varie, vous pouvez ne pas vouloir mettre en cache l'utilisateur actuel dans le DataContext (ou le définir lors de la création). J'utiliserais probablement une propriété dans le DataContext qui récupérait l'utilisateur courant de Session (d'une manière ou d'une autre) chaque fois que c'était nécessaire.

+0

La portée du contexte de données est par action - c'est assez éphémère. – tvanfosson

1

Si vous utilisez l'authentification Windows ou Forms, vous pouvez vérifier le HttpContext sans y introduire quoi que ce soit. Si vous n'êtes pas dans un contexte Web, prenez l'utilisateur dans le thread. Peut-être:

if(HttpContext.Current != null) 
{ 
    //grab the user from the HttpContext 
} 
else 
{ 
    //grab the user from the Thread 
} 
+0

Mais où mettriez-vous ce code?Lors de la création du contexte de données ou à chaque fois que l'utilitaire est appelé? – tvanfosson

+0

Le chemin de moindre résistance pourrait être ajouté dans votre implémentation SubmitChanges(). Cela élimine le besoin de transmettre quoi que ce soit et vos clients DataContext restent agréablement ignorants des détails. –

1

System.Threading.Thread.CurrentPrincipal devrait vous donner la réponse que vous recherchez.

Questions connexes