2017-03-05 1 views
0

J'ai lu beaucoup de messages sur des sujets similaires. J'ai un dépôt partielPartage de dbContext singleton à travers des dépôts en utilisant Ninject

public class EFPartRepository : IPartRepository 
    { 
     private ItemDBEntities dbContext = null; 
     public EFPartRepository(ItemDBEntities dbContext) 
     { 
      this.dbContext = dbContext; 
     } 
    } 

Je vais utiliser un autre référentiel nommé référentiel d'images

public class EFUploadedImageRepository : IUploadedImageRepository 
{ 
    private ItemDBEntities dbContext = null; 
    public EFUploadedImageRepository(ItemDBEntities dbContext) 
    { 
     this.dbContext = dbContext; 
    } 
} 

Comme ils seront utilisés dans la même demande, je veux qu'ils partagent un singleton de dbContext lors d'une demande, il n'y aura donc aucune exception "Un objet d'entité ne peut pas être référencé par plusieurs instances de IEntityChangeTracker"

Voici mon code de régression Ninject d'origine.

private static void RegisterServices(IKernel kernel) 
    { 
     kernel.Bind<IPartRepository>().To<EFPartRepository>(); 
     kernel.Bind<IUploadedImageRepository>().To<EFUploadedImageRepository>(); 
    } 

Ma question est, où est le meilleur endroit pour initialiser ce singleton, il peut être facilement utilisé par les différents référentiels au niveau mondial? Et comment le déclarer? (Le pire des cas est de toujours passer dbContext en paramètre lors de chaque appel).

Merci!

Répondre

1

Tout d'abord, pour lier un singleton, il suffit de faire: kernel.Bind<ItemDBEntities>.To<ItemDBEntities>().InSingletonScope();

Cependant, vous voudrez peut-être prendre en considération les implications. Le SingletonScope, par définition, vivra aussi longtemps que le noyau vit. Ainsi, à moins de recréer le noyau quelque part dans le cycle de vie de votre application, la connexion à la base de données sous-jacente restera ouverte pendant tout le cycle de vie. Toute implémentation SQL aura un nombre limité (même si très grand) de connexions disponibles (généralement limité par le nombre de sockets TCP disponibles). Cela signifie que si de nombreuses copies de votre application sont en cours d'exécution, vous ne pouvez plus en exécuter.

En outre, cette approche va forcer les connexions à vivre longtemps. Comment cela va-t-il se rétablir? que se passe-t-il si une exception est générée dans un référentiel entraînant un état corrompu pour le contexte db singleton?

Une approche beaucoup plus régulière consiste à configurer un référentiel avec un contexte à créer une fois dans la portée de la résolution.

Si vous souhaitez partager un contexte sous-jacent, créez un IMyDBContext, enregistrez-le dans l'étendue de résolution (par exemple pour le domaine Web -> champ de demande), puis injectez-le dans les deux référentiels. Ils auront le même contexte et les entités peuvent être partagées entre les deux, mais la connexion sera recréée pour chaque résolution.

+0

Merci beaucoup! Je vais essayer. Probablement je devrais avoir un conteneur dbContext, et le faire comme un singleton, partagé par tous les dépôts. Ce conteneur a un dbConext défini sur null initialement. Lorsqu'une requête arrive, le constructeur du contrôleur obtient un référentiel et crée le dbContext afin qu'il soit accessible à tous les dépôts depuis que le conteneur est partagé. Et il sera détruit une fois la demande terminée. – Chris

+0

@Chris correct. – zaitsman