2010-11-02 2 views
0

Ok, donc je reçois cette erreur des lignes:Erreur LINQ to SQL erratique: "l'opération ne peut pas être effectuée pendant un appel à SubmitChanges."

System.Data.Linq.DataContext.CheckNotInSubmitChanges() +42 
    System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) +54 

Ce que je fais est suivi de l'état et la connexion à chaque demande d'une application. L'application rend la sortie dans Json, Xml et Html.

La chose est l'erreur est erratique. Cela n'arrive que quelques fois. L'erreur a commencé à se produire lorsque j'ai commencé à faire des requêtes Ajax. J'ai été en mesure de déterminer que l'erreur se produit plus fréquemment avec les demandes rapides (c'est-à-dire si je clique sur un lien à plusieurs reprises).

Je crée une instance distincte de DataContext chaque fois que j'appelle le service qui lance l'erreur. J'ai vraiment du mal à comprendre quelle est la question ici et j'apprécierais vraiment toute orientation et/ou explication sur ce qui se passe. Je vous remercie.

* EDIT: **

[InvalidOperationException: The operation cannot be performed during a call to SubmitChanges.] 
    System.Data.Linq.DataContext.CheckNotInSubmitChanges() +80 
    System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) +73 
    Magic.Model.Sessions.SqlXmlSessionStore.SubmitChanges() in SqlXmlSessionStore.cs:17 
    Magic.Model.Sessions.SqlXmlSessionStore.UpdateSession(Session session) in SqlXmlSessionStore.cs:64 
    Magic.Web.SessionService.OpenSession(MagicRequestContext requestContext) in SessionService.cs:36 
    Magic.Web.SessionService.Magic.Model.Sessions.ISessionService.OpenSession(IRequestContext requestContext) in SessionService.cs:23 

Les méthodes mentionnées sont:

private bool SubmitChanges() 
{ 
    _sqlContext.SubmitChanges(ConflictMode.FailOnFirstConflict); 
    return _sqlContext.ChangeConflicts.Count == 0; 
} 

public bool UpdateSession(Session session) 
{ 
    var record = _sqlContext.SessionRecords.Single(x => x.SessionId == session.Key); 
    _converter.PopulateRecordData(session, record); 
    return SubmitChanges(); 
} 

Toute la classe de service de session ne fait qu'appeler SqlXmlSessionStore.UpdateSession (session) si la session est en db et active, ou SqlXmlSessionStore.InsertSession (session) si la requête est nouvelle et l'identifiant de session est manquant ou unique.

J'ai essayé de créer une nouvelle instance de DataContext chaque fois que j'ai fait un SubmitChanges(), mais cela m'a empêché d'avoir un objet Connection, même lorsque je tire le même conn. chaîne de paramètres. Cela pourrait-il être quelque chose à voir avec ma machine locale? Bon, alors j'ai fait quelque chose qui fonctionne, mais je ne suis pas sûr s'il y aura un problème avec ça que je ne prévois pas.

Je n'autorise le DataContext à soumettre qu'une seule fois. J'ai accompli en changeant les SubmitChanges() code:

private bool _canSubmit = true; 

    bool SubmitChanges(){ 
     if(_canSubmit) 
     { 
      _sqlContext.SubmitChanges(ConflictMode.FailOnFirstConflict); 
      _canSubmit = false; 
      return _sqlContext.ChangeConflicts.Count == 0;  
     } 
     return false; 
    } 

Cela semble encore comme un moyen très très hacky pour que cela fonctionne, et je voudrais aller au fond de la question, donc s'il vous plaît aviser si Quelqu'un a une idée de comment résoudre ce problème.

+1

Quelle erreur? Pouvez-vous poster le texte de l'exception? et une partie du code dans le DataContext en utilisant() –

Répondre

1

Il n'y aurait eu aucun moyen de le savoir à partir de mon message, mais j'ai trouvé le problème. J'ai mis en place l'injection de dépendance dans un HttpModule, et il y avait un verrou sur la fonction de configuration. Je pense qu'il était là à partir de l'ancien code que j'ai copié (et puis oublié) de quelque part quand j'ai commencé à apprendre à utiliser StructureMap. J'ai enlevé la serrure et cela a fonctionné. (enfin, au moins, il a commencé à générer de nouvelles erreurs sans rapport).

Oh, et la raison pour laquelle cela affectait mon DataContext était parce que les classes qui enveloppaient les instances du Datacontext étaient à l'intérieur du verrou.

0

Je vous suggère de joindre un débogueur et attraper l'exception dans l'acte. De là, vous devriez être capable de suivre d'où il vient.

Sinon, remplacez SubmitChanges et consignez la trace de pile sur un appel unique pour retrouver l'original de l'erreur.

1

Vous ne pouvez pas modifier l'ensemble de modifications dans SubmitChanges et vous ne pouvez pas appeler SubmitChanges dans les méthodes substituées des classes partielles. Je suppose que vous faites cela, mais je ne suis pas complètement vos fragments de code.

EDIT

Je ne comprends pas comment la durée de vie du DataContext est géré.Dans la première partie de la question que vous dites

I'm creating a separate instance of the DataContext each time I call the service

mais dans la deuxième partie que vous dites

I tried creating a new instance of the DataContext each time I did a SubmitChanges(), but that resulted in me not having a Connection object

La prochaine chose que je ne comprends pas comment est votre méthode modifiée qui appelle SubmitChanges ne fonctionne une fois, car il ne tient pas compte des modifications apportées aux données effectuées après le premier appel, il ne doit pas consigner toutes vos données ni aucun appel après le premier appel pour soumettre des modifications.

Les méthodes d'instance du Datacontext ne sont pas thread-safe, vous ne pouvez pas le mettre dans une variable globale au démarrage de l'application (faites-vous cela?); vous voulez généralement un nouveau Datacontext pour chaque requête HTTP, que vous pouvez faire en utilisant un framework Inversion of Control ou simplement en code, rajouter le dataconext au début de la requête et appeler les changements de soumission à la fin.

Une autre technique consiste à utiliser plusieurs DataContexts, à créer le datacontext, à effectuer les modifications, à appeler les chnages de soumission, à rejeter le DataContext, c'est très léger. Vous n'avez pas souvent besoin d'appeler les modifications de soumission plus d'une fois, la seule fois que j'ai fait ceci est de contrôler l'ordre d'exécution des instructions SQL.

Ce serait bien si vous pouviez construire un exemple minimal et publier le code entier.

+0

pas. ni. 2) Je crée un nouvel objet et InsertOnSubmit, puis SubmitChanges() 2) Je reçois un objet, le met à jour, puis SubmitChanges() – smartcaveman

+0

le datacontext? Où est-ce? –

+0

Non, j'ai une classe, SqlXmlSessionStore qui enveloppe le DataContext. Le booléen privé SubmitChanges() dans le SqlXmlSessionStore et effectue l'appel dans le code ci-dessus. – smartcaveman

Questions connexes