Entity Framework Meilleures pratiques de la logique métier?

J’utilise le framework Entity pour la première fois et je voudrais savoir si j’utilise la meilleure pratique.

J’ai créé une classe séparée dans ma logique métier qui gérera le contexte de l’entité. le problème que j’ai, c’est dans toutes les vidéos que j’ai vu qu’elles enveloppent généralement le contexte dans une déclaration using pour s’assurer qu’il est fermé, mais je ne peux évidemment pas le faire dans ma logique d’affaires car le contexte sera fermé avant que je puisse réellement utilise le?

Alors est-ce que ça va, ce que je fais? Quelques exemples:

public IEnumerable
GetLatestArticles(bool Authorised) { var ctx = new ArticleNetEntities(); return ctx.Articles.Where(x => x.IsApproved == Authorised).OrderBy(x => x.ArticleDate); } public IEnumerable
GetArticlesByMember(int MemberId, bool Authorised) { var ctx = new ArticleNetEntities(); return ctx.Articles.Where(x => x.MemberID == MemberId && x.IsApproved == Authorised).OrderBy(x => x.ArticleDate); }

Je veux juste m’assurer de ne pas construire quelque chose qui va mourir quand beaucoup de gens l’utilisent?

Cela dépend vraiment de la manière dont vous souhaitez exposer votre référentiel / magasin de données.

Je ne sais pas ce que vous entendez par “le contexte sera fermé, donc je ne peux pas faire de la logique commerciale”. Faites votre logique métier à l’ intérieur de l’instruction using. Ou si votre logique métier appartient à une classe différente, poursuivons. 🙂

Certaines personnes renvoient des collections concrètes depuis leur référentiel, auquel cas vous pouvez envelopper le contexte dans l’instruction using:

 public class ArticleRepository { public List
GetArticles() { List
articles = null; using (var db = new ArticleNetEntities()) { articles = db.Articles.Where(something).Take(some).ToList(); } } }

L’avantage de cela est de satisfaire aux bonnes pratiques en matière de connexion – ouvrez le plus tard possible et fermez le plus tôt possible.

Vous pouvez encapsuler toute votre logique métier dans l’instruction using.

Les inconvénients – votre référentiel prend conscience de la logique métier, ce que je n’aime pas personnellement, et vous vous retrouvez avec une méthode différente pour chaque scénario particulier.

La deuxième option – créer un contexte dans le référentiel et le rendre implémenter IDisposable.

 public class ArticleRepository : IDisposable { ArticleNetEntities db; public ArticleRepository() { db = new ArticleNetEntities(); } public List
GetArticles() { List
articles = null; db.Articles.Where(something).Take(some).ToList(); } public void Dispose() { db.Dispose(); } }

Et alors:

 using (var repository = new ArticleRepository()) { var articles = repository.GetArticles(); } 

Ou la troisième option (mon préféré), utilisez l’ dependency injection . Découplez tout le travail contextuel de votre référentiel et laissez le conteneur DI gérer la disposition des ressources:

 public class ArticleRepository { private IObjectContext _ctx; public ArticleRepository(IObjectContext ctx) { _ctx = ctx; } public IQueryable
Find() { return _ctx.Articles; } }

Le conteneur DI que vous avez choisi injectera le ObjectContext concret dans l’instanciation du référentiel, avec une durée de vie configurée (Singleton, HttpContext, ThreadLocal, etc.) et le supprimera en fonction de cette configuration.

Je l’ai configuré pour que chaque requête HTTP reçoive un nouveau contexte. Lorsque la demande est terminée, mon conteneur DI supprime automatiquement le contexte.

J’utilise également le modèle d’unité de travail ici pour permettre à plusieurs référentiels de fonctionner avec un seul contexte d’object.

Vous avez peut-être aussi remarqué que je préfère renvoyer IQueryable à partir de mon référentiel (par opposition à une liste concrète). Beaucoup plus puissant (encore risqué, si vous ne comprenez pas les implications). Ma couche de service exécute la logique métier sur IQueryable, puis renvoie la collection concrète à l’interface utilisateur.

C’est mon option la plus puissante, car elle permet un référentiel simple, l’unité de travail gère le contexte, la couche de service gère la logique applicative et le conteneur DI gère la durée de vie / la disposition des ressources / objects.

Faites-moi savoir si vous voulez plus d’informations à ce sujet – car il y a beaucoup de choses là-dessus, même plus que cette réponse étonnamment longue. 🙂

J’aurais le ctx en tant que variable privée dans chaque classe, puis créerais une nouvelle instance de cela à chaque fois, puis disposerais à la fin.

 public class ArticleService { private ArticleEntities _ctx; public ArticleService() { _ctx = new ArticleEntities(); } public IEnumerable
GetLatestArticles(bool Authorised) { return _ctx.Articles.Where(x => x.IsApproved == Authorised).OrderBy(x => x.ArticleDate); } public IEnumerable
GetArticlesByMember(int MemberId, bool Authorised) { return _ctx.Articles.Where(x => x.MemberID == MemberId && x.IsApproved == Authorised).OrderBy(x => x.ArticleDate); } public void Dispose() { _ctx.Dispose(); _ctx = null; } }

Puis en appelant ça.

 ArticleService articleService = new ArticleService(); IEnumerable
article = articleService.GetLatestArticles(true); articleService.Dispose(); // killing the connection

De cette façon, vous pouvez également append / mettre à jour d’autres objects dans le même contexte et appeler une méthode de sauvegarde qui enregistre toutes les modifications apscopes à la firebase database via l’entité.

D’après mon expérience, ce code n’est pas bon, car vous perdez la capacité de naviguer dans les relations via les propriétés de navigation.

 public List getArticles( ){ using (var db = new ArticleNetEntities()) { articles = db.Articles.Where(something).ToList(); } } 

En utilisant cette approche, vous ne pouvez pas utiliser le code suivant car a.Members est toujours nul (le contexte de la firebase database est proche et ne peut pas obtenir les données automatiquement).

 var articles = Data.getArticles(); foreach( var a in articles ) { if( a.Members.any(p=>p.Name=="miki") ) { ... } else { ... } } } 

Utiliser uniquement un contexte de firebase database global est une mauvaise idée car vous devez utiliser une fonction de suppression des modifications.

en un sharepoint votre application, faites ceci mais n’enregistrez pas les modifications et fermez la fenêtre

 var article= globalcontext.getArticleByID(10); article.Approved=true; 

puis dans un autre point d’application vous faites une opération et enregistrez

 //..... something globalcontext.saveChanges(); 

dans ce cas, la propriété approuvée d’article précédent est définie sur modifiée par le cadre de l’entité. Lorsque vous enregistrez, approuvé est défini comme vrai !!!

La meilleure approche pour moi est d’utiliser 1 contexte par classe. Vous pouvez passer le contexte à une autre méthode externe si vous avez besoin

 class EditArticle { private DbEntities de; private currentAricle; public EditArticle() { de = new DbEntities; //inizialize on new istance } loadArticleToEdit(Articele a){ // a is from another context currentArticle= de.Article.Single(p=>p.IdArticle==a.IdArticle){ } private saveChanges(){ ... pe.saveChanges(); } } 

Vous pouvez également stocker votre contexte à un niveau supérieur.

Par exemple, vous pouvez avoir une classe statique stockant le contexte actuel:

 class ContextManager { [ThreadStatic] public static ArticleEntities CurrentContext; } 

Ensuite, quelque part à l’extérieur, vous faites quelque chose comme ceci:

 using (ContextManager.CurrentContext = new ArticleEntities()) { IEnumerable
article = articleService.GetLatestArticles(true); }

Ensuite, dans GetLastestArticles, vous utilisez simplement le même ContextManager.CurrentContext.

Bien sûr, ce n’est que l’idée de base. Vous pouvez rendre cela beaucoup plus pratique en utilisant des fournisseurs de services, IoC, etc.

Vous pouvez commencer à préparer Entity Framework à partir de la couche d’access aux données en créant une classe de référentiel générique pour toutes les fonctions Entity Framework requirejses. Ensuite, vous pouvez l’utiliser dans la couche de gestion (encapsulé)

Voici les meilleures pratiques que j’ai utilisées pour Entity Framework dans les couches de données, d’entreprise et d’interface utilisateur.

Techniques utilisées pour cette pratique:

  1. Application des principes d’architecture SOLID
  2. Utilisation du modèle de conception de référentiel
  3. Un seul cours à faire (et vous le trouverez prêt)