5

在我把我的电脑踢到下周之前......

我已经检查了有关此的所有其他问题,但没有一个有解决方案。我已经删除了这段代码,但它仍然无法正常工作。

保存对象时出现此错误:NHibernate.AssertionFailure: null identifier

这是我的映射文件:

public class OrderMap : BaseMap<Order>
{
    public SalesOrderMap()
    {
        Id(x => x.Id).Column("OrderId");
    }
}

这是实体:

public class Order
{
    public virtual int Id { get; protected set; }
}

这是我的测试代码:

Order order = new Order();
ISession session = SessionFactory.GetCurrentSession();
session.SaveOrUpdate(order); <----EXCEPTION ON THIS LINE
session.Flush();

然后砰的一声……它打破了

[AssertionFailure: null identifier]
  NHibernate.Engine.EntityKey..ctor(Object identifier, String rootEntityName, String entityName, IType identifierType, Boolean batchLoadable, ISessionFactoryImplementor factory, EntityMode entityMode) +135
   NHibernate.Engine.EntityKey..ctor(Object id, IEntityPersister persister, EntityMode entityMode) +70
   NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) +545
   NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) +322
   NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) +130
   NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) +27
   NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event) +63
   NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event) +89
   NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event) +188
   NHibernate.Impl.SessionImpl.FireSaveOrUpdate(SaveOrUpdateEvent event) +259
   NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj) +256

如果有人感兴趣,这就是会话工厂的构建方式:

ControllerSource.SessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008.ConnectionString(DataConfig.ConnectionString))
                .Mappings(x => x.FluentMappings.Add(typeof (OrderMap)))
                .ExposeConfiguration(c =>{
                                             c.SetProperty("generate_statistics", "false");
                                             c.SetProperty("current_session_context_class", contextClass);
                                             c.SetProperty("cache.use_second_level_cache", "false");
                                             c.SetProperty("cache.use_query_cache", "false");
                                             c.SetProperty("connection.release_mode", "on_close");
                })
                .BuildSessionFactory();
4

3 回答 3

16

默认生成器是 Native,它将反过来使用 SQL Server 2008 的标识。我敢打赌,您没有在表定义的列上指定标识。

于 2011-11-15T16:11:43.510 回答
2

检查您的表是否没有干扰 INSERT 的触发器,或者可能在插入时调用存储过程。

当 NHibernate 插入实体时,它会向数据库询问新实体的自动生成的主键。

INSERT INTO [Order] (MyProperty) VALUES (@p0); select SCOPE_IDENTITY()

注意select SCOPE_IDENTITY()调用。

如果 SCOPE_IDENTITY 返回 NULL,那么您将获得 NHibernate.AssertionFailure: null 标识符异常。

例如,“INSTEAD OF INSERT”触发器将使 SCOPE_IDENTITY 返回 null,并触发 NHibernate 断言。

如果您发现触发干扰,您可以通过暂时禁用它来排除是否是实际问题。从长远来看,如果不再需要触发器,您可以决定是否完全摆脱它。

或者,您可以将插入包装在事务中;然后在插入之前禁用触发器,执行实体的实际保存/插入,然后重新启用触发器并提交事务。

于 2015-02-24T03:33:51.753 回答
1

您需要在尝试创建新实体时为实体分配一个 id,或者指定它在映射文件中的生成方式。将您的映射更改为:

Id(x => x.Id).Column("OrderId").GeneratedBy.Identity();
于 2011-11-15T15:18:57.270 回答