使用外部API调用处理并发异常

时间:2013-08-07 15:27:14

标签: asp.net-mvc entity-framework

我有以下POST编辑操作方法,主要执行两个Update操作: -

  1. 使用API​​调用编辑外部系统上的对象。
  2. 编辑系统数据库中的对象。

    [HttpPost]
    public ActionResult Create(RackJoin rj, FormCollection formValues)
    {string controllername = RouteData.Values["controller"].ToString();
    if (ModelState.IsValid)
    {  var message = "";
                    var status = "";
                    long assetid = new long();
                    XmlDocument doc = new XmlDocument();
                    using (var client = new WebClient())
                    {
                        var query = HttpUtility.ParseQueryString(string.Empty);
                        foreach (string key in formValues)
                        {
                            query[key] = this.Request.Form[key];
                        }
    
    query["username"] =  System.Web.Configuration.WebConfigurationManager.AppSettings["ApiUserName"];
    query["password"] =  System.Web.Configuration.WebConfigurationManager.AppSettings["ApiPassword"];
    string apiurl = System.Web.Configuration.WebConfigurationManager.AppSettings["ApiURL"];
    var url = new UriBuilder(apiurl);
    url.Query = query.ToString();
    try
    {
    string xml = client.DownloadString(url.ToString());
    
                            doc.LoadXml(xml);
     status = doc.SelectSingleNode("/operation/operationstatus").InnerText;
                            message = doc.SelectSingleNode("/operation/message").InnerText;
    }
                        catch (WebException ex)
                        {
                            ModelState.AddModelError(string.Empty, "Error occurred:" + ex.InnerException);
                        }
                    }
                     if (status.ToUpper() == "SUCCESS")
                {
                    repository.InsertOrUpdateRack(rj.Rack, User.Identity.Name, rj.Resource.RESOURCEID);
                    repository.Save();
                    return RedirectToAction("Index");
                }
                else
                {
                    ModelState.AddModelError(string.Empty, message.ToString());
    
                }
            }
        }
        catch (DbUpdateConcurrencyException ex)
        {
    
  3. 如上面的代码所示,我不会使用repository.save()更新系统上的对象,除非API返回“成功”。 但目前我面临以下问题: - 如果API返回“成功”但发生并发异常,则API将更新外部系统上的对象,但该对象不会在我们的系统上更新? 那么有办法处理这种情况吗?

1 个答案:

答案 0 :(得分:1)

解决这种情况并不容易。处理它的一种方法是要求外部API的设计者公开一种允许在先前调用中完成事务的方法。基本上你的第一个调用将修改外部系统,但有一些布尔标志表明这些更改仍然未决。然后更新系统,如果成功,您可以调用外部API将数据从挂起标记为有效。

如果您无法控制外部API并且它使第一次调用中的数据更改不可逆转,那么我担心您没有太多选择。在调用API之前,您可能记住在外部系统上修改的对象的状态,如果系统出现异常,恢复到之前的状态使用以前的值调用API。