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