Using EntityFramework v6, I am building a prototype to demonstrate concurrency validation in Web Api, as well as in a desktop application.
Essence:
public static class IRowVersionExtensions
{
public static string RowVersionAsString(this IRowVersion ivr)
{
return Convert.ToBase64String(ivr.RowVersion);
}
public static void SetRowVersion(this IRowVersion ivr, string rowVersion)
{
ivr.RowVersion = Convert.FromBase64String(rowVersion);
}
}
public interface IRowVersion
{
byte[] RowVersion { get; set; }
}
public class Department : IRowVersion
{
[Key]
public int Id { get; set; }
[Required, MaxLength(255)]
public string Name { get; set; }
public string Description { get; set; }
[Timestamp]
[ConcurrencyCheck]
public byte[] RowVersion { get; set; }
}
Dbcontext:
public class CompDbContext : DbContextEx
{
public CompDbContext()
: base("Company")
{
this.Configuration.LazyLoadingEnabled = false;
}
public DbSet<Department> Departments { get; set; }
}
The desktop application (console application) has the following code and throws a DbConcurrencyException as expected: http://pastebin.com/i6yAmVGc
Now, the API controller - when I open a page in two windows and edit one (and save), then try editing / saving the other, it does not throw an exception:
Api controller update action:
[HttpPatch, Route("")]
public Department UpdateDepartment(Department changed)
{
var original = dbContext.Departments.Find(changed.Id);
if (original == null)
this.NotFound();
if (Convert.ToBase64String(changed.RowVersion) != Convert.ToBase64String(original.RowVersion))
Console.WriteLine("Should error.");
original.RowVersion = changed.RowVersion;
original.Name = changed.Name;
original.Description = changed.Description;
dbContext.SaveChanges();
return original;
}
Api Call:
DepartmentVM.prototype.onSave = function (entity) {
var method = entity.id() ? 'PATCH' : 'PUT';
$.ajax({
url: '/api/departments',
method: method,
data: ko.toJSON(entity),
contentType: 'application/json',
dataType: 'JSON'
})
.done(function (data) {
alert('Saved');
entity.rowVersion(data.rowVersion);
entity.id(data.id);
})
.error(function (data) {
alert('Unable to save changes to department.');
});
};
When I break the line in the controller action:
if (Convert.ToBase64String(changed.RowVersion) != Convert.ToBase64String(original.RowVersion))
.RowVersion == original.RowVersion() ( ). save, changed.RowVersion!= Original.RowVersion(), - , ( , ).
- , , -API?