对象代码:
public class ParticipatingService
{
[Key]
public int Id { get; set; }
public int OptimisticVersion { get; set; }
[DisplayName("Receiver site")]
public int? TargetSiteId { get; set; }
[DisplayName("Receiver site")]
public virtual Hospital TargetSite { get; set; }
[DisplayName("Provider site")]
public int? SourceSiteId { get; set; }
[DisplayName("Provider site")]
public virtual Hospital SourceSite { get; set; }
[DisplayName("Provider person")]
public int? SourcePersonId { get; set; }
[DisplayName("Provider person")]
public virtual Person SourcePerson { get; set; }
[DisplayName("Study")]
public int StudyId { get; set; }
[DisplayName("Study")]
public virtual Study Study { get; set; }
[DisplayName("Start date")]
public virtual PartialDate StartDate { get; set; }
[DisplayName("End date")]
public virtual PartialDate EndDate { get; set; }
public int? RegInvestigatorFormId { get; set; }
public PartialDate AuthorizationDate { get; set; }
public bool IsNationalCoordinator { get; set; }
[DisplayName("Role")]
public int RoleId { get; set; }
[DisplayName("Role")]
public virtual ParticipatingServiceCLI Role { get; set; }
[DisplayName("Affiliation type")]
public int? AffiliationId { get; set; }
public virtual AffiliationCLI Affiliation { get; set; }
public bool IsFromActivePersonSite
{
get
{
foreach (PersonSite personSite in SourcePerson.PersonSites.ToList().OrderByDescending(ps => ps.StartDate.Date))
{
if (personSite.SiteId == SourceSiteId)
{
return personSite.IsActive();
}
}
return false;
}
}
public bool IsFromSecondarySite
{
get
{
foreach (PersonSite personSite in SourcePerson.PersonSites.ToList().OrderByDescending(ps => ps.StartDate.Date))
{
if (personSite.SiteId == SourceSiteId)
{
return personSite.RelationType.StringId.Equals("Secondary");
}
}
return false;
}
}
public override bool IsActive()
{
return !this.IsDeleted && this.SourcePerson != null && this.Study != null && this.TargetSite != null && this.SourcePerson.IsActive() && this.TargetSite.IsActive() && (this.EndDate == null || this.EndDate.Date == null || this.EndDate.Date > DateTime.Now);
}
}
存储库代码:
public virtual T Update(T obj)
{
System.Data.Entity.Infrastructure.DbEntityEntry<T> dbEntry = this.Context.Entry<T>(obj);
System.Data.Entity.Infrastructure.DbPropertyValues x = dbEntry.GetDatabaseValues();
int optimisticValue = x.GetValue<int>("OptimisticVersion");
if ((int)this.Context.Entry<T>(obj).GetDatabaseValues()["OptimisticVersion"] == obj.OptimisticVersion)
{
obj.OptimisticVersion++;
obj.LastModificationDate = DateTime.Now;
this.Context.Entry<T>(obj).State = EntityState.Modified;
this.Context.SaveChanges();
return obj;
}
throw new DBConcurrencyException("The selected item is obsolete !");
}
问题 :
我正在使用具有 CRUD 操作 (DRY) 的通用管理器和通用存储库。问题是当试图保存一个对象时(只有一种类型的解决方案会导致该问题),它在第一次更新时运行良好。然后尝试再次更新同一个对象会导致NullReferenceException
. GetDatabaseValues()
我试图拆分以下行:
(int)this.Context.Entry<T>(obj).GetDatabaseValues()["OptimisticVersion"] == obj.OptimisticVersion
分成多行:
System.Data.Entity.Infrastructure.DbEntityEntry<T> dbEntry = this.Context.Entry<T>(obj);
System.Data.Entity.Infrastructure.DbPropertyValues x = dbEntry.GetDatabaseValues();
int optimisticValue = x.GetValue<int>("OptimisticVersion");
有谁知道为什么它可以第一次获取数据库值并在下次调用时抛出异常?
这是堆栈跟踪:
System.Data.Objects.EntityEntry.DetectChangesInComplexType(StateManagerMemberMetadata topLevelMember, StateManagerMemberMetadata complexMember, Object complexValue, Object oldComplexValue)
at System.Data.Objects.EntityEntry.DetectChangesInProperties(Boolean detectOnlyComplexProperties)
at System.Data.Objects.EntityEntry.InternalGetOriginalValues(Boolean readOnly)
at System.Data.Objects.EntityEntry.GetUpdatableOriginalValues()
at System.Data.Entity.Internal.StateEntryAdapter.GetUpdatableOriginalValues()
at System.Data.Entity.Internal.InternalEntityEntry.get_OriginalValues()
at System.Data.Entity.Internal.InternalEntityEntry.GetDatabaseValues()
at System.Data.Entity.Infrastructure.DbEntityEntry`1.GetDatabaseValues()
at EORTC.BASE.DAL.EORTCBaseRep`1.Update(T obj) in C:\Projects\_Prisma\EORTC.BASE.DAL\EORTCBaseRep.cs:line 121
at EORTC.BASE.BLL.EORTCBaseManager`1.Update(T obj, Boolean validate) in C:\Projects\_Prisma\EORTC.BASE.BLL\EORTCBaseManager.cs:line 58
at Prisma.BLL.ParticipatingServiceManager.Update(ParticipatingService obj, Boolean validate) in C:\Projects\_Prisma\Prisma.BLL\Managers\Service\ParticipatingServiceManager.cs:line 96
at Prisma.Web.Controllers.ParticipatingServiceController.Edit(Int32 id, FormCollection collection) in C:\Projects\_Prisma\Prisma.Web\Controllers\Service\ParticipatingServiceController.cs:line 172
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
at System.Web.Mvc.MvcHandler.<>c__DisplayClasse.<EndProcessRequest>b__d()
at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)