3

Je dois exécuter une procédure stockée SQL à chaque fois avant d'interroger mon objet ObjectContext. Ce que je veux accomplir est de mettre le CONTEXT_INFO à une valeur qui sera utilisée plus tard avec la plupart de mes requêtes.Exécuter une procédure stockée SQL avant chaque requête générée par EntityFramework

Quelqu'un at-il fait cela? Est-ce possible?

[EDIT]

Actuellement, je suis atteinte en ouvrant la connexion et l'exécution de la procédure stockée dans mon constructeur ObjectContext comme ceci:

public partial class MyEntitiesContext 
{  
    public MyEntitiesContext(int contextInfo) : this() 
    { 
     if (Connection.State != ConnectionState.Open) 
     { 
      Connection.Open(); // open connection if not already open 
     } 

     var connection = ((EntityConnection)Connection).StoreConnection; 

     using (var cmd = connection.CreateCommand()) 
     { 
      // run stored procedure to set ContextInfo to contextInfo 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.CommandText = "[dbo].[SetContextInfo]"; 
      cmd.Parameters.Add(new SqlParameter("@ci", _contextInfo)); 
      cmd.ExecuteNonQuery(); 
     } 
     // leave the connection open to reuse later 
    } 
} 

Puis dans mon test d'intégration:

[TestMethod] 
public void TestMethod1() 
{ 
    using (var ctx = new MyEntitiesContext(1)) 
    {    
     Assert.AreEqual(2, ctx.Roles.ToList().Count); 
     Assert.AreEqual(2, ctx.Users.ToList().Count); 
    } 
} 

Mais cela m'oblige à laisser la connexion ouverte - ceci est source d'erreurs car j'ai toujours besoin de CONTEXT _INFO, et un autre développeur peut facilement faire:

[TestMethod] 
public void TestMethod2() 
{ 
    using (var ctx = new MyEntitiesContext(1)) 
    {    
     // do something here 
     // ... more here :) 
     ctx.Connection.Close(); // then out of the blue comes Close(); 
     // do something here 
     Assert.AreEqual(2, ctx.Roles.ToList().Count); 
     Assert.AreEqual(2, ctx.Users.ToList().Count); // this fails since the where 
     // clause will be: 
     // WHERE ColumnX = CAST(CAST(CONTEXT_INFO() AS BINARY(4)) AS INT) 
     // and CONTEXT_INFO is empty - there are no users with ColumnX set to 0 
     // while there are 2 users with it set to 1 so this test should pass 
    } 
} 

Les moyens ci-dessus que je peux écrire le code comme dans mon test et everthing est vert (youpi!) Mais mon collègue utilise le code de TestMethod2 quelque part dans son entreprise logique et il est tout f'd up - et personne ne sait où et pourquoi puisque tous les tests sont verts:/

[EDIT2]

This blog post ne répond certainement pas à ma question, mais résout effectivement mon problème. Peut-être aller avec NHibernate sera mieux adapté à mon but :)

+0

+ 1 concept intéressant. – tster

+0

merci - ce que je le veux pour est le filtrage des données de locataire dans une application multi-locataire. Je ne veux pas passer le TenantId à chaque procédure stockée à la place j'utilise des vues qui s'appuient sur CONTEXT_INFO donc je voudrais toujours définir CONTEXT_INFO avant d'interroger la base de données. Et encore j'aimerais utiliser EF. J'ai eu cette idée à partir d'un article de blog: http://blogs.imeta.co.uk/jyoung/archive/2010/03/22/845.aspx –

Répondre

0

Enfin j'ai trouvé la réponse. Je peux envelopper la connexion en utilisant le toolkit EFProvider wraper de EFProviderWrappers. Pour ce faire, je dois principalement dériver de EFProviderWrapperConnection et remplacer la méthode DbConnection.Open(). Je l'ai déjà essayé avec le fournisseur de Tracing et ça marche bien. Une fois que je l'ai testé avec ma solution, j'ajouterai plus d'informations.

1

Nous avons utilisé ce modèle. Mais la façon dont nous l'avons fait était d'appeler la procédure stockée comme la première opération dans chaque contexte DB.

+0

Ceci est une sorte d'erreur sujette - peut-être pourrait être réalisé bien avec AOP (comme PostSharp) mais je ne voudrais pas le faire de cette façon. En fait, je pourrais écrire mon propre fournisseur ADO.NET pour envelopper SqlClient et toujours avant de fournir un DbConnection d'exécuter la procédure stockée d'abord, puis retourner la connexion. Mais je ne sais pas si cela est possible avec l'architecture de SqlClient. –

+0

Nous avons placé le code qui appelle la procédure stockée dans sa propre méthode, puis nous pourrions faire un compte et vérifier le nombre de fois qu'il est appelé correspond à la nombre de fois que le contexte db est utilisé. –

+0

Bonne idée. Encore quelqu'un peut appeler ctx.Connection.Close(); et vos tests comptant les utilisations de ctx et les appels de méthode ne valent rien. –

Questions connexes