Orchard 1.8 - 保存独特字段的记录

时间:2015-04-03 09:55:49

标签: save unique orchardcms orchardcms-1.8 irepository

我在迁移中定义了我的表中的一列是唯一的。如果我尝试保存违反此唯一性约束的记录,我当然会收到异常:

A duplicate value cannot be inserted into a unique index.

要使用IRepository创建和更新方法保存记录,因为它没有相应的部分。收到上面的异常后,我抓住它然后启动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也会自动尝试将记录刷新到数据库中。我试图改变交易范围,但它没有奏效。有没有办法解决这个问题?

2 个答案:

答案 0 :(得分:2)

在处理内容部分记录时,您不能使用Unique约束。原因是那些是早期创建的,当时还没有数据传递给它(所有属性都为空/ null)。这发生在ContentManager内。因此,这些记录的所有属性都必须是可空的且非唯一的。

但是,您可以对映射到您创建的记录的类使用唯一/非空约束,并直接通过IRepository使用。

答案 1 :(得分:0)

如果这是针对ContentPart的,并且您可以在.NET中为您的字段创建唯一值,那么您始终可以在ContentHandler中使用OnInitializing事件。

例如,这适用于db中唯一的Sku字段:

public class ProductPartHandler: ContentHandler
{
    public ProductPartHandler(IRepository<ProductPartRecord> repository)
    {
        Filters.Add(StorageFilter.For(repository));
        OnInitializing<ProductPart>((context, part) =>
        {
            part.Sku = Guid.NewGuid().ToString();
        });
    }
}

只要你可以产生一个你的字段支持的某种保证的唯一值,那么你总是可以在处理程序中设置它来处理唯一约束,然后用你想要的真实值更新它。