【问题标题】:Handling concurrency access for deleting an object using Ajax.actionlink使用 Ajax.actionlink 处理删除对象的并发访问
【发布时间】:2012-03-31 10:24:07
【问题描述】:

我的 asp.net MVC 应用程序中有以下视图,其中包含用于删除对象的 ajax.actionlink:-

<table id="incrementanswer">
    <tr>
        <th>
            Description
        </th>
        <th>
            Answer 
        </th>
        <th></th>
    </tr>

@foreach (var answer in Model.Answers.OrderBy(a => a.IsRight))
{
       <tr id =  @answer.AnswersID>

        <td>
            @Html.DisplayFor(modelItem => answer.Description)
        </td>
        <td>
            @Html.DisplayFor(modelItem => answer.Answer_Description.description)
        </td>
        <td>

       @{ string i = "Are uou sure you want to delete " + @answer.Description.ToString() + " ?";}
         @Ajax.ActionLink("Delete", "Delete", "Answer",
        new { id = answer.AnswersID },
          new AjaxOptions
          {
              Confirm = i,
              HttpMethod = "Post",
              OnBegin = string.Format(
                       "disablelink({0})",
                       Json.Encode(answer.AnswersID)),
              OnSuccess = string.Format(
                        "deleteconfirmation3({0},{1})",
                        Json.Encode(answer.AnswersID), Json.Encode(answer.Description))
          })  </td>
        </tr>}</table>

以及将由上述 ajax 链接调用的以下 post delete 操作方法:-

[HttpPost] 
        public void Delete(int id) 
        {       var a = repository.FindAnswer(id); 
                repository.DeleteAnswer(a); 
                repository.Save();} 

以及以下 OnSuccess 脚本:-

function deleteconfirmation3(rid, rname) {
    $('#' + rid).remove();
    jAlert(rname + ' Was Deleted Succsfully succsfully', 'Deletion Confirmation');}

目前,如果两个用户访问同一个视图,然后他们都点击了与同一个对象关联的删除链接,那么其中一个请求将引发空异常;那么我如何在操作方法端和视图端处理这个问题以向用户显示友好的消息;在这两种情况下:-

  1. var a = repository.FindAnswer(id); 返回 null 例外?
  2. 或者repository.Save();没有删除任何记录?

BR

编辑:-

我将发布操作方法更新为以下内容:-

[HttpPost]
    public ActionResult Delete(int id)
    {

        try
        {
            Thread.Sleep(1000);
            var a = repository.FindAnswer(id);

            repository.DeleteAnswer(a);
            repository.Save();
            return Json(new { IsSuccess = "True", id = id, description = a.Description }, JsonRequestBehavior.AllowGet); 
        }
        catch (ArgumentNullException) {
            return Json(new { IsSuccess = "False" }, JsonRequestBehavior.AllowGet);  }}

在视图上我将 ajax.actionlink 更新为以下内容:-

@{ string i = "Are uou sure you want to delete " + @answer.Description.ToString() + " ?";}
         @Ajax.ActionLink("Delete", "Delete", "Answer",
        new { id = answer.AnswersID },
          new AjaxOptions
          {
              //OnBegin = "deleteconfirmation1",
              Confirm = i,
              HttpMethod = "Post",
              OnBegin = string.Format(
                       "disablelink({0})",
                       Json.Encode(answer.AnswersID)),

              OnSuccess =  "myresponse" 
        })

和 Onsuccess 脚本:-

    function myresponse(data) {
    if (data.IsSuccess == "True") 
    {
        $('#' + data.id ).remove();
        jAlert(data.description + ' Was Deleted Succsfully succsfully', 'Deletion Confirmation');
    }
    else {
        $('#' + data.id).remove();
        jAlert(data.description + 'record has already been deleted', 'aaaa');
    } 
}

上面的代码在我测试时运行良好,但是这种方法听起来可以接受吗,因为我以前没有写过类似的东西? BR

【问题讨论】:

  • 我不认为这是开发一些事务以允许仅通过一个浏览器窗口打开一个数据项的意义。这个问题的目标是什么?并发问题总是与更新操作而不是删除有关。如果用户尝试删除已删除的项目,只需向他显示消息,这不会损害您的业务逻辑。
  • 在我的应用程序中,多个用户将有权删除同一个对象。因此,即使该对象已被其他用户删除,向用户返回消息已成功删除对象也可能会导致一些不一致问题 ....

标签: asp.net-mvc-3 jquery concurrency


【解决方案1】:

添加一个检查,如果记录存在则删除它,否则显示一条消息,指出记录已被删除...

[HttpPost] 
public ActionResult Delete(int id) 
{       var a = repository.FindAnswer(id); 
        if(/*check if a is not null*/){
        repository.DeleteAnswer(a); 
        repository.Save();
        return Json(new{ IsSuccess="True", id=id,description=a.Description });
        }else{
            // display a message record already been deleted
          return Json(new{ IsSuccess="False" });
       }     

 } 

显然,您需要将返回类型从 void 更改为 ActionResultJsonResult

@Ajax.ActionLink("Delete", "Delete", "Answer",
        new { id = answer.AnswersID },
          new AjaxOptions
          {
              Confirm = i,
              HttpMethod = "Post",
              OnBegin = string.Format(
                       "disablelink({0})",
                       Json.Encode(answer.AnswersID)),
              OnSuccess = "myResponse"
          })

成功的处理程序会像

function myResponse(data){
 if(data.IsSuccess=="True")
   jAlert(data.description + ' Was Deleted Succsfully succsfully', 'Deletion Confirmation');
  else {
   alert("record has already been deleted");
  }

}

【讨论】:

  • 感谢您的回复。但是,如果我在您的帖子中提到的 Post 操作方法上执行上述检查“if(/*check if a is not null*/)”,那么两个用户可能会得到相同的结果,即“a”不为 null,如果他们正好同时点击“删除”这样问题还是会出现???是不是我理解的代码逻辑错了?
  • 查看我的更新。我没有对 post action uisng "if(/*check if a is not null*/)"" 执行检查,而是返回不同的 Json 数据;一个在 Try 上,另一个在 Catch 上(ArgumentNullException)。这就是可以接受吗??..
  • 无论用户多快点击同一个删除链接,一个请求都会首先到达服务器,因此第二个(不是最快的)请求将获得已删除的记录跨度>
  • 你尝试实现的方法也很好,不能多说,如果它适合你,那就去吧
  • 感谢您的回复;但是如果两个删除请求同时到达,它们将被并行处理,因此它们将在以下两个检查中收到相同的结果:- 1. var a = repository.FindAnswer(id) 2. if(/*check if a 不为空*/)。所以这意味着在发布操作方法上删除记录之前检查记录的存在可能不会在大型网站上一直有效?我的观点有效吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多