I currently have an entity that I'm trying to edit through my MVC 3 web app. I receive an DbUpdateConcurrencyException
when trying to perform a the client wins approach I got from MSDN's post Using DbContext in EF 4.1 Part 9: Optimistic Concurrency Patterns. The weird part is that this only happens on this particular entity and there I'm not doing anything different from the other. Also, it only happens when updating from a null to a value. The Properties giving the error when updating from null value to a DateTime
value are DispositionLetterDate
and DateDisposition
.
Class:
public class A22
{
public A22()
{
this.IsArchived = false;
this.A22StatusId = (int)AStatus.Open;
}
[Key]
public int Id { get; set; }
[Required]
[StringLength(100, ErrorMessage="A22 Number cannot exceed 100 characters")]
public string Number { get; set; }
[Display(Name="Manual")]
public int ManualId { get; set; }
[Display(Name="SGMLID")]
public string SGMLId { get; set; }
[Required]
[DataType(DataType.Date)]
[Display(Name="Date Received")]
public DateTime DateReceived { get; set; }
[Display(Name= "Status")]
[EnumDataType(typeof(A22Status))]
public int A22StatusId { get; set; }
[Display(Name="Priority")]
[EnumDataType(typeof(A22Priority))]
public int A22PriorityId { get; set; }
[Display(Name="Providing Disposition")]
public string ProvidingDisposition { get; set; }
[Display(Name="Final Disposition")]
public bool FinalDisposition { get; set; }
[Display(Name="Is Archived")]
public bool IsArchived { get; set; }
[Display(Name="Created By")]
public int CreatedById { get; set; }
[Display(Name="Date Created")]
public DateTime DateCreated { get; set; }
[ConcurrencyCheck]
[Display(Name="Date Modified")]
public DateTime DateModified { get; set; }
[Display(Name = "Disposition Date")]
public DateTime? DateDisposition { get; set; }
[Display(Name = "Date Disposition Letter Sent")]
public DateTime? DispositionLetterDate{ get; set; }
// Virtual Properties
[ForeignKey("CreatedById")]
public virtual User CreatedBy { get; set; }
[ForeignKey("ManualId")]
public virtual Manual Manual { get; set; }
public virtual ICollection<A22Manual> A22ManualsImpacted { get; set; }
public virtual ICollection<A22Task> A22TasksImpacted { get; set; }
public virtual ICollection<A22Comment> Comments { get; set; }
public virtual ICollection<A22HistoryLog> HistoryLogs { get; set; }
}
Controller:
[HttpPost]
public ActionResult Edit(A22 a22)
{
var d = new A22Repository().Find(a22.Id);
var changes = TrackChanges(d, a22);
if (ModelState开发者_JAVA技巧.IsValid) {
if (!string.IsNullOrEmpty(changes))
{
repository.InsertOrUpdate(a22);
this.repository.AddHistory(a22, changes);
repository.Save();
}
return RedirectToAction("Details", new { id = a22.Id });
} else {
ViewBag.PossibleManuals = d.ManualId == default(int) ? manualRepo.GetManualList() :
manualRepo.GetManualList(d.ManualId);
ViewBag.APriority = repository.GetAPriorityList(d.APriorityId);
ViewBag.AStatus = repository.GetAStatusList(d.APriorityId);
return View();
}
}
}
View:
@model TPMVC.Web.Models.A22
@{
Layout = "~/Views/Shared/_BlendLayoutLeftOnly.cshtml";
ViewBag.Title = "Edit";
}
<h2>Edit A22# @Model.Number</h2>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.CreatedById)
@Html.HiddenFor(model => model.DateCreated)
@Html.HiddenFor(model => model.DateModified)
@Html.Partial("_CreateOrEdit")
<div class="newItemLabel">
<strong style="padding-right: 145px;">@Html.LabelFor(model => model.AStatusId)</strong>
@{
Html.Telerik().DropDownList()
.Name("AStatusId")
.BindTo((IEnumerable<SelectListItem>)ViewBag.AStatus)
.HtmlAttributes(new { @style = "width: 200px;" })
.Render();
}
@Html.ValidationMessageFor(model => model.AStatusId)
</div>
<div class="newItemLabel">
<strong style="padding-right: 77px;">@Html.LabelFor(model => model.FinalDisposition)</strong>
@Html.EditorFor(model => model.FinalDisposition)
</div>
<div class="newItemLabel">
<strong style="padding-right: 44px;">@Html.LabelFor(model => model.DateDisposition)</strong>
@{
Html.Telerik().DatePickerFor(model => model.DateDisposition)
.Render();
}
</div>
<div class="newItemLabel">
<strong style="padding-right: 44px;">@Html.LabelFor(model => model.DispositionLetterDate)</strong>
@{
Html.Telerik().DatePickerFor(model => model.DispositionLetterDate)
.Render();
}
</div>
<div class="newItemLabel">
<strong style="padding-right: 110px;">@Html.LabelFor(model => model.IsArchived) </strong>
@Html.EditorFor(model => model.IsArchived)
</div>
<p>
<input type="submit" value="Save" />
</p>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Thinking it was could have been something with the data annotations, I decided to define the properties with this issue to optional using the Fluid API.
modelBuilder.Entity<A22>().Property(a => a.DateDisposition).IsOptional();
modelBuilder.Entity<A22>().Property(a => a.DispositionLetterDate).IsOptional();
I basically need a fresh pair of eyes to see if I'm missing something. Is there other property that is making it behave this way?
Thanks in advance.
I'm mapping nullable DateTime properties like following without IsOptional methods. Also it works fine with MS SQL and MySQL by me.
this.Property(t => t.CreatedDate).HasColumnName("CreatedDate");
this.Property(t => t.ModifiedDate).HasColumnName("ModifiedDate");
in class derived from EntityTypeConfiguration. I'm using Code First approach.
精彩评论