首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ASP.NET MVC部分视图回发、不一致更新和Bizzare行为

ASP.NET MVC部分视图回发、不一致更新和Bizzare行为
EN

Stack Overflow用户
提问于 2016-07-21 21:22:38
回答 2查看 524关注 0票数 2

我正在开发一个ASP.Net MVC应用程序,并且在试图通过部分回发更新数据库中的数据时遇到了一个bizzare问题。在HTTP、AJAX等方面,我仍然是新手,所以我希望这是一个明显的错误。

基本上,当我试图更新将内容区域链接到评估的表时,更新有时起作用,有时不起作用。bizzare的特点是,在我发布后,我直接从MVC应用程序查询数据库,以确保预期的更改实际上已经完成(这就是所有ViewBag.DebugInfo在下面的代码中所做的)。在任何情况下,查询都返回我希望看到的内容。但是,当我通过SSMS查询表时,我发现更改有时只会发生。

我的MVC应用程序对表的直接查询如何显示更新已经完成,而我却清楚地看到它不是通过SSMS完成的?有没有静音回滚什么的?这是令人恼火的,任何帮助都将不胜感激。

几个信息:

  • 当我从MVC之外的assessmentContent类运行"saveTheData“函数时,它总是成功的。
  • 更新在第一次发布时总是成功的。
  • 更新成功的时间仅为后续帖子的一半。
  • 当更新不成功时,来自MVC应用程序的直接查询检查似乎确实显示了更新一直到表。
  • 我在失败中几乎找不出一个模式。也就是说,每当我试图更新到更高的contentId值时,它都是成功的,如果我试图更新到较低的contentId,它就不会成功。例如,从1(数学)到2(读)的值总是会被更新,但是相反的不会。如果它是父视图中的第一篇文章,或者它是通过Linqpad更新的,那么这个模式就不会显化。
  • 我将insert、update和delete触发器放在写入日志表的数据库表上,以查看这些更改是否正在回滚。但是日志表中没有失败的条目。但我也不知道回滚是否也会撤销触发器。
  • 我对dbo.fn_dblog()进行了筛选,以获得操作= 'LOP_ABORT_XACT',但是没有(尽管我没有受过训练以适应这一困难的视图)。

这里是我的类,它获取和更新数据:

代码语言:javascript
运行
复制
public class assessmentContent {

    public int? assessmentId { get; set; }
    public List<short> baseline { get; set; } = new List<short>();
    public List<short> comparison { get; set; } = new List<short>();

    public assessmentContent() { if (assessmentId != null) refreshTheData(); }

    public assessmentContent(int assessmentId) {
        this.assessmentId = assessmentId;
        refreshTheData();
    }

    public void saveTheData() {

        List<short> upserts = comparison.Except(baseline).ToList();
        List<short> deletes = baseline.Except(comparison).ToList();

        foreach (var upsert in upserts)
            reval.ach.addAssessmentContent(assessmentId, upsert);

        foreach (var delete in deletes)
            reval.ach.deleteAssessmentContent(assessmentId, delete);

        refreshTheData();
    }

    void refreshTheData() {
        baseline = reval.ach.assessmentContent(assessmentId).ToList();
        comparison = reval.ach.assessmentContent(assessmentId).ToList();
    }

}

当我在MVC应用程序之外使用它时,逻辑工作得很好。因此,例如,如果我通过linqpad使用它,就没有问题。我应该指出,assessmentContent()可以命名为'getAssessmentContent()‘。

,这是我的部分视图控制器,以及一些相关代码:

代码语言:javascript
运行
复制
public class ContentsModel {
    public int? assessmentId { get; set; }
    public List<short> comparison { get; set; }
}

public class ContentsController : Controller {

    public static string nl = System.Environment.NewLine;

    public ActionResult ContentsView(int assessmentId) {

        ViewBag.DebugInfo = new List<string>();

        var vm = new ContentsModel();
        vm.assessmentId = assessmentId;
        vm.comparison = reval.ach.assessmentContent(assessmentId).ToList();

        return View("~/Views/ach/Contents/ContentsView.cshtml", vm);
    }

    public ActionResult update(ContentsModel vm) {

        ViewBag.DebugInfo = new List<string>();
        sqlFetch();

        ViewBag.DebugInfo.Add($"VM Pased In {vm.assessmentId}  c{vm.comparison.intsJoin()}");
        sqlFetch();

        var crud = new crud.ach.assessmentContent((int)vm.assessmentId);
        ViewBag.DebugInfo.Add($"newly fetched CRUD {crud.assessmentId}  b{crud.baseline.intsJoin()}  c{crud.comparison.intsJoin()}");
        sqlFetch();

        crud.comparison = vm.comparison;
        ViewBag.DebugInfo.Add($"CRUD after crud_comparison = vm_comparison {crud.assessmentId}  b{crud.baseline.intsJoin()}  c{crud.comparison.intsJoin()}");
        sqlFetch();

        crud.saveTheData();
        ViewBag.DebugInfo.Add($"CRUD after save {crud.assessmentId}  b{crud.baseline.intsJoin()}  c{crud.comparison.intsJoin()}");
        sqlFetch();

        vm.comparison = crud.comparison;
        ViewBag.DebugInfo.Add($"VM after vm_comparison = crud_comparison {vm.assessmentId}  c{vm.comparison.intsJoin()}");
        sqlFetch();

        return PartialView("~/Views/ach/Contents/ContentsView.cshtml", vm);
    }

    void sqlFetch() {
        ViewBag.DebugInfo.Add(
                "SQL Fetch " +
                Sql.ExecuteOneColumn<short>("select contentId from ach.assessmentContent where assessmentId = 12", connections.research).intsJoin()
            );
    }

}

public static partial class extensions {

    public static string intsJoin(this IEnumerable<short> ints) {

        var strings = new List<string>();
        foreach (int i in ints)
            strings.Add(i.ToString());
        return string.Join(",", strings);
    }

}

我知道,我可能没有3层体系结构或模型-视图-控制器结构最好在这里实现。

您会注意到,在我的绝望中,我在模型更改的每一个点都直接检查了数据库表。

部分视图:

代码语言:javascript
运行
复制
@model reval.Views.ach.Contents.ContentsModel
@using reval
@{Layout = "";}

<div id="contentDiv">

    <form id="contentForm">

        @Html.HiddenFor(m => m.assessmentId)

        @Html.ListBoxFor(
            m => m.comparison,
            new reval.ach.content()
                .GetEnumInfo()
                .toMultiSelectList(
                    v => v.Value,
                    d => d.DisplayName ?? d.Description ?? d.Name,
                    s => Model.comparison.Contains((short)s.Value)
                ),
            new { id = "contentListBox" }
        )

    </form>

    <br/>
    @foreach(string di in ViewBag.DebugInfo) {
        @Html.Label(di) 
        <br/>
    }

</div>

<script>

    $("#contentListBox").change(function () {

        $.ajax({

            url: "/Contents/update",
            type: "get",
            data: $("#contentForm").serialize(), 
            success: function (result) {
                $("#contentDiv").html(result);
            },
            error: function (request, status, error) {
                var wnd = window.open("about:blank", "", "_blank");
                wnd.document.write(request.responseText);
            }
        });
    })

</script>

,最后是主视图中的调用:

代码语言:javascript
运行
复制
<div id="testDiv">
@if (Model.assessment != null && Model.assessment.assessmentId != null) {

    Html.RenderAction("ContentsView", "Contents", new { assessmentId = Model.assessment.assessmentId });   

}
</div>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-19 16:37:46

我讨厌当我解决一个问题的时候,没有确切地确定我为解决问题所做的事情。但是,在处理了上面的一些代码之后,我让它正确和一致地工作了。

然而,我几乎可以肯定,这个问题与asp.net mvc在从服务器传递数据到客户端和向后传递数据时的工作方式产生了误解。也就是说,当服务器上的C#视图模型和控制器的数据被发送到客户机上的html/asp时,它们仍然处于活动状态。我有一种预感,客户端数据与C#对象不一样,但我确实感觉到,ASP.Net MVC正在更新C#对象,以应对回发上的任何更改。现在,我清楚地知道,实际上,C#对象被完全丢弃并完全实例化(调用了构造函数和所有相关的结果),并重新填充了来自客户端的数据。即使客户端没有进行任何更改,这也是正确的。

我认为实际上正在对数据库进行更新。没有出现回滚现象。但是,在重新实例化时发生了一些事情,导致了对数据库的第二次调用,并重新设置了它们的值。这可以解释为什么它在ASP.net MVC之外工作得很好。这就解释了为什么在我意识到这一点之后,我才解决了这个问题。

我认为这一反应是准确的,但不是精确的。我的意思是,我相信指南解决了这个问题,即使它没有确定上面的违规代码的确切行。由于它的准确性,我认为这是公平的游戏标记它作为一个答案。由于不精确,我愿意把别人的反应作为答案,如果他们能更精确。然而,由于上面的代码不再被使用,所以它都是为了学习目的。

票数 1
EN

Stack Overflow用户

发布于 2016-07-21 21:31:35

您是否确定您正在对数据库进行的事务已提交或已完成?可能会有其他交易同时进行,从而回退您正在进行的事务。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38514580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档