2009-03-26 7 views
0

Je suis vraiment coincé ici.Structure carte InstanceScope.Hybrid avec asp.net mvc misbehaves

J'ai une application mvc asp.net et j'utilise StructureMap 2.5.3 (SM) pour injecter des classes de service et de référentiel dans mes contrôleurs. Tous les contrôleurs sont fabriqués par une usine SM. J'ai également un datacontex Linq to SQL que je voulais mettre en cache par hybride.

public class DBRegistry:Registry 
{ 
    public DBRegistry() 
    { 
     ForRequestedType<SharpShopDataContext>() 
      .CacheBy(StructureMap.Attributes.InstanceScope.Hybrid) 
      .TheDefault.IsThis(new SharpShopDataContext()); 
    } 
} 

La mise en cache ne semble pas fonctionner et j'ai des problèmes avec le datacontext à cause de cela.

Plusieurs demandes de navigateur tous retournent le même dbcontext ?! Dans l'une de mes classes de référentiel, j'ai mis ce code. Debug.WriteLine ("hashcode db:" + db.GetHashCode() + "" + DateTime.Now.ToString());

où db = DataContext imprimer aussi les hashcodes du dépôt en utilisant le db et le service en utilisant le référentiel, voici une impression de plusieurs demandes:

hashcode service: 18 6238972 26-3-2009 : 59: 34

dépôt hashcode: 21756593 26-3-2009 18:59:34

db hashcode: 7043935 26-3-2009 18:59:34

Service hashcode: 59389065 26- 3-2009 18:59:34

dépôt hashcode: 8331620 26-3-2009 18:59:34

db hashcode: 7043935 26-3-2009 18:59:34

hashcode service: 18 11291358 26-3-2009 : 59: 38

dépôt hashcode: 13848497 26-3-2009 18:59:38

db hashcode: 7043935 26-3-2009 18:59:38

Service hashcode: 42509361 26- 3-2009 18:59:38

dépôt hashcode: 56101068 26-3-2009 18:59:38

db hashcode: 7043935 26-3-2009 18:59:38

que vous pouvez voir est le 7043935 hashcode pour la datacontext chaque fois pour chaque requête, mais le service et le référentiel obtiennent une nouvelle instance et un hashcode à chaque fois. J'obtiens des erreurs bizarres à cause de cela, par exemple une exception dataAconcurrency car dbcontext a une valeur d'origine de 4 webrequests, alors que la base de données a été modifiée par une autre source.

+0

en changeant InstanceScope à PerRequest, donne le même résultat, tous les hashcodes db sont les mêmes, en créant manuellement deux dbcontexts séparés donnent deux hashcodes différents ... – user81129

Répondre

0

J'ai une solution de contournement, mais pas heureux parce que je sais que je dois changer beaucoup de code, et je l'ai découvert par essais et erreurs.

J'utilise maintenant:

  ForRequestedType<ISharpShopDataContextWrapper>() 
      .CacheBy(StructureMap.Attributes.InstanceScope.Hybrid) 
      .TheDefaultIsConcreteType<SharpShopDataContextWrapper>(); 

L'injection/la mise en cache des interfaces semble œuvres. Voici la mise en œuvre de l'interface + enveloppe de béton.

Donc, ça ressemble vraiment à un bug dans SM, ou est-ce qu'il me manque quelque chose?

public interface ISharpShopDataContextWrapper 
{ 
    SharpShopDataContext DataContext 
    { 
     get; 
    } 
} 

public class SharpShopDataContextWrapper : ISharpShopDataContextWrapper 
{ 
    SharpShopDataContext db; 

    public SharpShopDataContextWrapper() 
    { 
     db = new SharpShopDataContext(); 
    } 
    public SharpShopDataContext DataContext 
    { 
     get { return db; } 
    } 
} 
2

C'est certainement une ligne de problème:

.TheDefault.IsThis 

Vous spécifiez une instance spécifique, c'est ce qu'il fait pour retourner le même, même si la spécification PerRequest. Notez que vous avez changé pour (dans votre contournement):

.TheDefaultIsConcreteType<SharpShopDataContextWrapper>(); 

Ps. Je n'ai pas utilisé HybridScope, mais j'ai une application de production qui utilise la portée d'instance par défaut (PerRequest) et elle en donne certainement une nouvelle chaque fois qu'elle passe un datacontext. Si vous voulez contrôler précisément la façon dont il est instancié, essayez l'une des méthodes qui acceptent une expression, de cette façon vous envoyer:

() => new MyDataContext() 
3

Si vous essayez d'obtenir SM pour créer un seul DataContext par HttpRequest que votre nouveau configuration Registry devrait fonctionner

ForRequestedType<ISharpShopDataContextWrapper>() 
      .CacheBy(StructureMap.Attributes.InstanceScope.Hybrid) 
      .TheDefaultIsConcreteType<SharpShopDataContextWrapper>(); 

InstanceScope.Hybrid est le SM (v2.5.3) valeur ENUM vous devriez utiliser si vous voulez un cycle de vie « une fois par requête fil ou ASP.NET » (laisse aller à la source Chad Myers, SM contributor)

Si vous configurez correctement votre infrastructure d'application, vous ne devez pas "devoir modifier beaucoup de code". Je serais intéressant de savoir pourquoi vous avez décidé de créer une classe wrapper pour votre SharpShopDataContext? Le LinqToSql DataContext est déclarée en tant que classe partielle de sorte que vous pouvez facilement créer une classe partielle SharpShopDataContext qui implémente des interfaces supplémentaires:

LinqToSql généré définition de classe partielle

public partial class SharpShopDataContext: System.Data.Linq.DataContext{ 
    /*Linq2Sql gen here*/ 
} 

Votre définition de classe partielle

public partial class SharpShopDataContext: ISharpShopDataContext{ 
    /*your implementation here*/ 
} 

Vous pouvez lire certains de Jeremy Miller's StructureMap articles. Une fois que vous avez une bonne compréhension de ses capacités, vous allez probablement refactoriser toute votre application MVC. Je sais que ma base d'application MVC actuelle est hautement configurable/testable à cause de SM IoC (et des charges de bateau de trial/error/smell/refactor).