2016-07-21 3 views
2

Я разрабатываю приложение ASP.Net MVC, и у меня возникает проблема с bizzare при попытке обновить данные в моей базе данных с помощью частичной обратной передачи. Я все еще новичок, когда дело доходит до HTTP, AJAX и т. Д., Поэтому я надеюсь, что это очевидная ошибка.ASP.NET MVC Partial View Post-Back, непоследовательное обновление и поведение Bizzare

В принципе, когда я пытаюсь обновить таблицу, связывающую области содержимого с оценками, обновление иногда работает, иногда нет. Что такое bizzare, так это то, что после того, как я отправляю сообщение, я напрямую запрашиваю базу данных из приложения MVC, чтобы убедиться, что ожидаемое изменение было сделано фактически (вот что делает все ViewBag.DebugInfo в коде ниже). В каждом случае запрос возвращает то, что я надеюсь увидеть. Но затем, когда я запрашиваю таблицу через SSMS, я вижу, что изменение только иногда проходит.

Как получается, что прямой запрос к таблице из моего приложения MVC показывает, что обновление прошло, в то время как я могу ясно видеть, что это не было через SSMS? Есть тихий откат или что-то в этом роде? Это сходит с ума, и любая помощь будет высоко оценена.

Несколько бит информации:

  • При запуске функции «saveTheData» из класса assessmentContent ниже за пределами MVC, всегда успешно.
  • Обновление всегда успешное на первом посту.
  • Обновление выполнено только около половины времени на последующих сообщениях.
  • Когда обновление не выполнено, запрос прямого запроса из приложения MVC тем не менее, похоже, показывает, что обновление полностью переместилось в таблицу.
  • Я могу с трудом разглядеть образец в неудачах. А именно, кажется, что всякий раз, когда я пытаюсь обновиться до более высокого значения contentId, это успешно, если я пытаюсь обновить до более низкого contentId, это не так. Например, обновление от значения 1 (Math) до 2 (Чтение) всегда будет проходить, но наоборот. Этот шаблон не отображается, если он является первым сообщением из родительского представления или обновляется через Linqpad.
  • Я поместил триггеры вставки, обновления и удаления в таблицу базы данных, которые записывают в таблицу протоколирования, чтобы увидеть, возможно ли изменения были отброшены. Но никаких записей в таблице журналов при сбое нет. Но я также не знаю, будут ли откат отменять триггеры.
  • Я запросил dbo.fn_dblog(), отфильтрованный для Operation = 'LOP_ABORT_XACT', но ничего (хотя у меня нет подготовленных глаз для этого трудного представления).

Вот мой класс, который извлекает и обновляет данные:

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, проблем нет. Я должен упомянуть, что valuContent() можно назвать «getAssessmentContent()».

Вот мой контроллер для частичного вида, и некоторый связанный Код:

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-го уровня или структуру Model-View-Controller лучшие реализованную Вот.

Вы заметите, что в моем отчаянии я поставил прямую проверку в таблицу базы данных при каждой точке изменения моделей.

Частичный Вид:

@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> 

И, наконец, вызов от главного Вид:

<div id="testDiv"> 
@if (Model.assessment != null && Model.assessment.assessmentId != null) { 

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

} 
</div> 

ответ

1

Ненавижу это, когда я решаю проблему, не пытаясь точно определить, что я сделал для ее решения. Но после работы над некоторым из вышеприведенного кода, я получил его работу правильно и последовательно.

Я почти уверен, однако, что проблема связана с непониманием работы asp.net mvc при передаче данных с сервера на клиент и обратно. А именно, у меня появилась идея, что мои модели и контроллеры C# на сервере все еще были живы, когда их данные отправлялись на html/asp на клиенте. У меня была догадка, что данные клиента не совпадают с объектами C#, но я чувствовал, что ASP.Net MVC обновлял объект C# для любых изменений в postback. Теперь мне ясно, что на самом деле объекты C# полностью отбрасываются и полностью инстанцируются (с вызванными конструкторами и всеми связанными последствиями) и заселяются данными от клиента. И это верно, даже если на клиенте не производятся изменения.

Я думаю, что обновления фактически были сделаны в базе данных. Откат не происходил. Но что-то происходило при повторной инстанцировании, что вызывало второй звонок в базу данных и сброс их значений. Это объясняет, почему он отлично работает вне ASP.net MVC. Это объясняет, почему я решил проблему после этой реализации.

Я бы назвал этот ответ точным, но не точным. Под этим я подразумеваю, что я уверен, что руководство решает проблему, даже если она не фиксирует точные строки вышеописанного кода. Из-за точности, я рассматриваю это честную игру, чтобы отметить ее как ответ. Из-за неточности я открыт для того, чтобы пометить чужой ответ как ответ, если они могут быть более точными. Однако, поскольку вышеприведенный код больше не используется, все это только для целей обучения.

1

Вы уверены, что сделка вы делаете в базу данных привержен или завершено? В то же время могут происходить другие транзакции, которые могут откатывать те, которые вы делаете.

+0

Я определенно не уверен, но в то же время я скажу, что единственная причина, по которой я подозреваю, что проблема с транзакцией связана с симптомами. Я не пишу никакого явного кода, относящегося к транзакциям. Сообщите мне, есть ли у вас какие-либо рекомендации относительно того, как я буду устранять проблемы, кроме моих попыток, упомянутых в моем ответе. Благодарю. – pwilcox

+0

Хорошо, я думаю, вы меня поменяли правильно. Мне рано говорить с комфортом, но я, возможно, решил проблему, добавив явные транзакции и зафиксировав их в моем базовом коде доступа к данным. Даже если это не так, важно, чтобы любой заинтересованный пользователь с аналогичной проблемой рассматривал как возможную проблему, поэтому я возвращаю свой ответ. Если на самом деле у меня есть решение, я отправлю обратно. СПАСИБО!!!. – pwilcox

+0

С сожалением сообщаю, что это не проблема. Более того, порядок упорядочения ошибок, описанных выше, похоже, не имеет места. – pwilcox