-1
votes

Assurez-vous d'appeler le succès de l'API et de vous sauver le succès

Bonjour j'ai trouvé un problème lorsque j'utilise ASP.NET MVC avec EF et appelez Web API d'un autre site Web (qui utilise également l'entité framework) Le problème est que

je veux m'assurer que les SAVECANGES MVC () CODE> et Web API SAVECHANGES () CODE> réussissent à la fois ensemble. P>

Voici My Dream Pseudo Code P>

public ActionResult Operation()
{
    Code Insert Update Delete....

    bool testMvcSaveSuccess = db.TempSaveChanges();  //it does not have this command.

    if(testMvcSaveSuccess == true)
    {
       bool isApiSuccess = CallApi(); //insert data to Other Web App


       if(isApiSuccess == true)
       {
          db.SaveChanges(); //Real Save
       }
    }
}


3 commentaires

Alors pourquoi pas Callapi d'abord, après cela, les savechanges MVC basées sur le succès de l'API ou non?


@ BEBEBEIZHU: Appelez le premier succès API, mais vous êtes-vous sûr que MVC SAVECHANGANGE () sera le succès? MVC peut sauvegarder l'échec


Donc, vous voulez deux opérations dans une transaction..Data Le problème de la cohérence se produit également dans le microservice, désolé je ne suis pas familier avec cette partie.


4 Réponses :


0
votes

Oui, vous pouvez.

Vous devez surcharger le .Savechanges dans la classe de contexte où il s'appellera d'abord vérifié, puis appelez le régulier après.

ou Créez votre propre Tempsavechanges () dans la classe de contexte appelez-le alors si un appel réussi SAVECHANGES de it.


0 commentaires

2
votes

Donc, il n'y a rien de tel que Tempsavechanges car il y a quelque chose encore mieux: Transactions .

transaction est une indisposable (peut être utilisée dans un bloc à l'aide de bloc) et a des méthodes telles que commit et Rollback .

petit exemple: xxx

J'ai extrait cet exemple de mon github exercice.entityframework référentiel. N'hésitez pas à étoiler / cloner / fourchette ...


2 commentaires

Donc, si changecount> 0, il serait sûr de 100% que transaction.commit () ne manquera pas correctement?


Jusqu'à présent, je sais: Savechanged met actuellement à jour votre base de données de manière «verrouillée» (puisque nous sommes dans une transaction). Cela signifie que tout sera le succès ou rien ne sera changé. L'appel commettez quittera cet état verrouillé. Rollback annulera tous les changements et quittera l'état de verrouillage. Notez que cette exécution de transaction dépend de la technologie de stockage que vous utilisez actuellement. Pour plus d'informations, vous pouvez vérifier Transactions SQL ou démarrez le profileur SQL et vérifiez toutes les requêtes



0
votes

Ce que vous faites référence est appelé atomicité : vous voulez que plusieurs opérations réussissent tous, soit aucun d'entre eux. Dans le contexte d'une base de données, vous obtenez cette via transactions (si la base de données prend en charge). Cependant, dans votre cas, vous avez besoin d'une transaction qui s'étend sur deux systèmes disjoints. Un objectif général (certains cas particuliers ont des solutions simples) une mise en œuvre robuste d'une telle transaction aurait certaines exigences sur les deux systèmes, et nécessitent également une persistance supplémentaire.

Fondamentalement, vous devez être capable de récupérer gracieusement d'une butée soudaine à tout moment pendant la séquence. Chacune des bases de données que vous utilisez est probablement acide conforme, vous pouvez donc compter sur chaque transaction de DB pour remplir l'exigence d'atomicité (elles réussissent ou échouent). Par conséquent, tout ce que vous devez vous inquiéter est la séquence des deux transactions DB. Votre exigence sur les deux systèmes est un moyen de déterminer une posteriori si une certaine opération a été effectuée ou non.

exemple de processus de processus:

  1. l'opération commence
  2. génère un identifiant de transaction unique et persistez (avec des données de demande)
  3. apporter des modifications à la DB locale et commettre
  4. appelez API Web externe
  5. transaction d'indicateur comme terminé (ou supprimez-le)
  6. L'opération se termine

    récupération:

    1. Obtenez toutes les transactions en attente (non complétées) de Store
    2. Vérifiez si l'évolution attendue de la DB locale a été faite
    3. Demandez à Web API si le changement attendu a été effectué
    4. Si aucun des changements n'a été effectué ou que les deux modifications ont été apportées, la transaction est effectuée: Supprimer / drapeau.
    5. Si l'une des modifications a été faite, mais pas l'autre, alors rétablissez le changement effectué (révert la transaction) ou effectuez le changement qui n'était pas (reprendre la transaction) => puis supprimer / le drapeau.

      Maintenant, comme vous pouvez le constater, il est rapidement compliqué, spécialement si "déterminer si des modifications ont été apportées" est une opération non triviale. Quelle est une solution commune à cela consiste à utiliser cet identifiant de transaction unique comme moyen de déterminer quelles données ont besoin d'attention. Mais à ce stade, il devient très spécifique à la demande et dépend entièrement de quelles sont les opérations spécifiques. Pour certaines applications, vous pouvez simplement réexécuter la totalité de l'opération (puisque vous disposez des données complètes de la demande stockées dans la transaction) dans l'étape de récupération. Certains cas particuliers n'ont pas besoin de persister la transaction car il existe d'autres moyens d'atteindre les mêmes choses, etc.


0 commentaires

0
votes

OK, clarifions un peu les choses.

Vous avez une application MVC A1 , avec sa propre base de données D1 Vous avez ensuite une API, appelons-le A2 avec sa propre base de données D2 .

Vous voulez du code dans A1 , qui fait une tempête de Temp sauvey dans d1 , déclenche ensuite un appel à A2 et si la réponse est réussie Ensuite, il enregistre les données temporaires de d1 au bon endroit cette fois-ci.

Basé sur votre pseudo-code, je vous suggère de créer une deuxième table dans laquelle vous enregistrez vos données "temporaires" dans d1 . Donc, votre base de données a une table supplémentaire et le flux est comme celui-ci:

Tout d'abord, vous enregistrez vos données A1 dans cette table, vous appelez ensuite A2 , les données sont enregistrées dans D2 , A1 < / forte> reçoit la confirmation et appelle une méthode qui déplace les données de la deuxième table à l'endroit où elle devrait être.

scénarios à considérer:

  1. Sauvegarde des données temporaires dans d1 œuvres, mais l'appel à A2 échoue. Vous désignez maintenant les données orphelines avec un travail de lot ou appelez simplement quelque chose qui le supprime lorsque l'appel à A2 échoue.

  2. L'appel à A2 réussit et l'appel à d1 échoue, vous avez maintenant des données temporelles dans d1 qui a échoué se déplacer vers la bonne table. Vous pouvez ajouter un drapeau à la deuxième table contre chaque ligne, ce qui indique que le deuxième appel à A2 a réussi afin que ces données doivent se déplacer au bon endroit, lorsque cela est possible. Vous pouvez avoir un service ici qui fonctionne périodiquement et s'il trouve des données avec le drapeau défini sur true, il déplace les données au bon endroit.

    Il existe d'autres moyens de gérer les scénarios comme celui-ci. Vous pouvez utiliser un système de file d'attente pour gérer cela. Chaque ligne de données devient un message, vous attribuez une carte d'identité unique, un GUID, qui est essentiellement un corrélationid et c'est la même chose dans les deux systèmes. Même si un système tombe en panne, lors de la sauvegarde, les données seront sauvegardées et toutes sont bonnes dans le monde et à cause de l'ID commun, vous pouvez toujours le lier correctement.


0 commentaires