我是MVC的EF新手。我需要在应用程序中实现并发检查。
我正在关注有关EF中并发处理的内置支持的MSDN帮助:http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application
但在我的情况下,我正在进行部分更新,所以我使用AJAX调用服务器端方法来执行此操作。在这个服务器端方法中,我需要实现并发检查。
按照教程我在代码中进行了必要的更改:
首先在我的数据库中创建了时间戳列:
ALTER TABLE dbo.Job
ADD RowVersion rowversion NULL;
在实体类中:
[Timestamp]
public byte[] RowVersion { get; set; }
在我的Mapping类中(使用流畅的api):
this.Property(t =>
t.RowVersion).HasColumnName("RowVersion").IsConcurrencyToken();
在我的视图模型类中:
[Timestamp]
public byte[] RowVersion { get; set; }
在我的视图文件中:
@Html.HiddenFor(x => x.RowVersion)
JS文件中的(ajax调用):
function UpdateJobTransferStatus(jobTransferStatusId, newJobTransferSatusId, currentAction, statusName) {
var hdnJobId = $("#JobId").val();
//var hdnRowVersion = $("#RowVersion").val();
var hdnAccountingId = $("#hdnAccountingSystemId").val();
$.ajax(
{
type: "GET",
url: ResolveUrl("~/Api/Job/UpdateJobTransferStatus"),
dataType: "json",
contentType: "application/json; charset=utf-8",
data: { jobId: hdnJobId, currentAction: currentAction, jobTransferStatusId: newJobTransferSatusId, accountingSystemId: hdnAccountingId },//,rowVersion: hdnRowVersion },
success: function (data) {
GetPreviousOrNextStatus(jobTransferStatusId, currentAction, statusName, hdnAccountingId);
},
error: function (result) {
}
});
}
最后在我的控制器中(在我的ajax调用上):
我根据MSDN(using System.Data.Entity.Infrastructure;
)
[System.Web.Http.HttpGet]
public HttpResponseMessage UpdateJobTransferStatus(int jobId, int currentAction,
int jobTransferStatusId, short accountingSystemId, byte[] rowVersion)
在这里,我总是得到'null
'的'byte[] rowVersion
',无论我是否在AJAX调用中将该值作为参数发送(我在代码片段中留了注释,我粘贴在这里。)
我已经检查过,每次成功插入/更新执行时,列都会在DB中进行更新,并且视图模型在每次页面加载时从此DB获取此RowVersion列的最新值。
在MSDN示例中,他们已经提交了表单,但我正在使用AJAX调用,除了我试图保持每个方面都相同。
发送整个视图模型对象可能会为我完成这项工作,但我不需要整个对象来执行我的部分更新(虽然我没试过)。
如何将rowVersion
传递给ajax电话?
答案 0 :(得分:1)
您应该将其作为字符串发送并将其转换回服务器上的字节数组。这是因为HTML页面将其作为字符串存储在base64格式的input
标签(隐藏类型)中。 c#侧的细微变化应该可以解决它。
查看:现有代码无需更改,传入HiddenFor
时byte[]
的默认行为是将其转换为Base 64字符串
c#code
[System.Web.Http.HttpGet]
public HttpResponseMessage UpdateJobTransferStatus(int jobId, int currentAction, int jobTransferStatusId, short accountingSystemId, string rowVersion){
var rowVersionBytes = System.Convert.FromBase64String(rowVersion); // convert to byte array
}
使用Javascript:
function UpdateJobTransferStatus(jobTransferStatusId, newJobTransferSatusId, currentAction, statusName) {
var hdnJobId = $("#JobId").val();
var hdnRowVersion = $("#RowVersion").val(); // this will be a string
var hdnAccountingId = $("#hdnAccountingSystemId").val();
$.ajax(
{
type: "GET",
url: ResolveUrl("~/Api/Job/UpdateJobTransferStatus"),
dataType: "json",
contentType: "application/json; charset=utf-8",
data: { jobId: hdnJobId, currentAction: currentAction, jobTransferStatusId: newJobTransferSatusId, accountingSystemId: hdnAccountingId, rowVersion: hdnRowVersion }
success: function (data) {
GetPreviousOrNextStatus(jobTransferStatusId, currentAction, statusName, hdnAccountingId);
},
error: function (result) {
}
});
}
最后,因为您实际上正在执行更新,这应该是HttpPost或HttpPut而不是HttpGet。
我在你的sql中再看到一个错误,它可能会对现有数据造成意外问题。列RowVersion
应标记为NOT NULL
,即使在现有表上,当指定rowversion
类型时,Sql Server将使用值填充所有现有记录。
ALTER TABLE dbo.Job
ADD RowVersion rowversion NOT NULL