Orchard 1.8 - 使用唯一字段保存记录
Orchard 1.8 - Saving record with unique field
我在迁移中将 table 的其中一列定义为唯一。如果我尝试保存违反此唯一性约束的记录,我当然会收到异常:
A duplicate value cannot be inserted into a unique index.
为了保存记录,我使用了 IRepository Create 和 Update 方法,因为它没有相应的部分。收到上述异常后,我捕获了它,然后启动 AddModelError 以停止保存过程。 Neverthless Orchard 在那之后给了我另一个例外:
[AssertionFailure: null id in MyModule.Models.MyRecord entry (don't flush the Session after an exception occurs)]
NHibernate.Event.Default.DefaultFlushEntityEventListener.CheckId(Object obj, IEntityPersister persister, Object id, EntityMode entityMode) +267
NHibernate.Event.Default.DefaultFlushEntityEventListener.GetValues(Object entity, EntityEntry entry, EntityMode entityMode, Boolean mightBeDirty, ISessionImplementor session) +95
NHibernate.Event.Default.DefaultFlushEntityEventListener.OnFlushEntity(FlushEntityEvent event) +139
NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities(FlushEvent event) +448
NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) +283
NHibernate.Event.Default.DefaultAutoFlushEventListener.OnAutoFlush(AutoFlushEvent event) +84
NHibernate.Impl.SessionImpl.AutoFlushIfRequired(ISet`1 querySpaces) +471
NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) +477
NHibernate.Impl.AbstractSessionImpl.List(IQueryExpression queryExpression, QueryParameters parameters) +223
NHibernate.Impl.ExpressionQueryImpl.List() +189
NHibernate.Linq.DefaultQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery) +61
NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) +262
NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) +26
Remotion.Linq.QueryableBase`1.GetEnumerator() +83
System.Linq.Enumerable.ToDictionary(IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer) +173
System.Linq.Enumerable.ToDictionary(IEnumerable`1 source, Func`2 keySelector) +125
Orchard.Data.Migration.DataMigrationManager.GetFeaturesThatNeedUpdate() +311
Orchard.Modules.Data.Migration.<GetNotifications>d__6.MoveNext() +219
System.Linq.<SelectManyIterator>d__14`2.MoveNext() +507
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +536
System.Linq.Enumerable.ToList(IEnumerable`1 source) +80
Orchard.UI.Admin.Notification.NotificationManager.GetNotifications() +151
Orchard.UI.Admin.Notification.AdminNotificationFilter.OnResultExecuting(ResultExecutingContext filterContext) +380
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +245
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +97
System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +241
System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +111
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +19
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +51
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +111
Orchard.Mvc.Routes.HttpAsyncHandler.EndProcessRequest(IAsyncResult result) +95
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
如果我正确理解是什么原因造成的,即使我添加了模型错误,Orchard 也会自动尝试将记录刷新到数据库中。我试图更改事务范围,但没有用。有没有办法解决这个问题?
处理内容部分记录时不能使用Unique
约束。原因是那些是在还没有数据传递给它的时候创建的(所有属性都是empty/null)。这发生在 ContentManager
内。因此,这些类型的记录的所有属性都必须可以为空且不唯一。
但是您可以在 类 上使用 unique/not-null 约束,这些约束映射到您通过 IRepository
直接创建和使用的记录。
如果这是针对 ContentPart 的,并且您有办法在 .NET 中为您的字段创建唯一值,那么您始终可以在您的 ContentHandler 中为您的部分使用 OnInitializing 事件。
例如,这适用于数据库中的唯一 Sku 字段:
public class ProductPartHandler: ContentHandler
{
public ProductPartHandler(IRepository<ProductPartRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
OnInitializing<ProductPart>((context, part) =>
{
part.Sku = Guid.NewGuid().ToString();
});
}
}
只要您可以生成您的字段支持的某种有保证的唯一值,那么您始终可以在处理程序中设置它来处理唯一约束,然后稍后用您想要的实际值更新它。
我在迁移中将 table 的其中一列定义为唯一。如果我尝试保存违反此唯一性约束的记录,我当然会收到异常:
A duplicate value cannot be inserted into a unique index.
为了保存记录,我使用了 IRepository Create 和 Update 方法,因为它没有相应的部分。收到上述异常后,我捕获了它,然后启动 AddModelError 以停止保存过程。 Neverthless Orchard 在那之后给了我另一个例外:
[AssertionFailure: null id in MyModule.Models.MyRecord entry (don't flush the Session after an exception occurs)]
NHibernate.Event.Default.DefaultFlushEntityEventListener.CheckId(Object obj, IEntityPersister persister, Object id, EntityMode entityMode) +267
NHibernate.Event.Default.DefaultFlushEntityEventListener.GetValues(Object entity, EntityEntry entry, EntityMode entityMode, Boolean mightBeDirty, ISessionImplementor session) +95
NHibernate.Event.Default.DefaultFlushEntityEventListener.OnFlushEntity(FlushEntityEvent event) +139
NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities(FlushEvent event) +448
NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) +283
NHibernate.Event.Default.DefaultAutoFlushEventListener.OnAutoFlush(AutoFlushEvent event) +84
NHibernate.Impl.SessionImpl.AutoFlushIfRequired(ISet`1 querySpaces) +471
NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) +477
NHibernate.Impl.AbstractSessionImpl.List(IQueryExpression queryExpression, QueryParameters parameters) +223
NHibernate.Impl.ExpressionQueryImpl.List() +189
NHibernate.Linq.DefaultQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery) +61
NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) +262
NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) +26
Remotion.Linq.QueryableBase`1.GetEnumerator() +83
System.Linq.Enumerable.ToDictionary(IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer) +173
System.Linq.Enumerable.ToDictionary(IEnumerable`1 source, Func`2 keySelector) +125
Orchard.Data.Migration.DataMigrationManager.GetFeaturesThatNeedUpdate() +311
Orchard.Modules.Data.Migration.<GetNotifications>d__6.MoveNext() +219
System.Linq.<SelectManyIterator>d__14`2.MoveNext() +507
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +536
System.Linq.Enumerable.ToList(IEnumerable`1 source) +80
Orchard.UI.Admin.Notification.NotificationManager.GetNotifications() +151
Orchard.UI.Admin.Notification.AdminNotificationFilter.OnResultExecuting(ResultExecutingContext filterContext) +380
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +245
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +97
System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +241
System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +111
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +19
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +51
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +111
Orchard.Mvc.Routes.HttpAsyncHandler.EndProcessRequest(IAsyncResult result) +95
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
如果我正确理解是什么原因造成的,即使我添加了模型错误,Orchard 也会自动尝试将记录刷新到数据库中。我试图更改事务范围,但没有用。有没有办法解决这个问题?
处理内容部分记录时不能使用Unique
约束。原因是那些是在还没有数据传递给它的时候创建的(所有属性都是empty/null)。这发生在 ContentManager
内。因此,这些类型的记录的所有属性都必须可以为空且不唯一。
但是您可以在 类 上使用 unique/not-null 约束,这些约束映射到您通过 IRepository
直接创建和使用的记录。
如果这是针对 ContentPart 的,并且您有办法在 .NET 中为您的字段创建唯一值,那么您始终可以在您的 ContentHandler 中为您的部分使用 OnInitializing 事件。
例如,这适用于数据库中的唯一 Sku 字段:
public class ProductPartHandler: ContentHandler
{
public ProductPartHandler(IRepository<ProductPartRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
OnInitializing<ProductPart>((context, part) =>
{
part.Sku = Guid.NewGuid().ToString();
});
}
}
只要您可以生成您的字段支持的某种有保证的唯一值,那么您始终可以在处理程序中设置它来处理唯一约束,然后稍后用您想要的实际值更新它。