NHibernate - 非唯一对象异常
NHibernate - NonUniqueObjectException
TL;DR 版本是这样的:尝试在单元测试中删除实体时,我不断收到 NonUniqueObjectException。如果 NHibernate 不使用 Equals 方法或 GetHashCode,谁能告诉我它如何检查缓存和比较对象?
我有一个应用程序正在尝试使用以下代码进行测试。
[Test]
public void _04_Category_Delete_Test() {
using(var lifetime = container.BeginLifetimeScope()) {
ICategoryRepository categoryRepository = lifetime.Resolve<ICategoryRepository>();
DefaultCommandBus commandBus = lifetime.Resolve<DefaultCommandBus>();
IMappingEngine mapper = lifetime.Resolve<IMappingEngine>();
Category category = categoryRepository.Get(x => x.Title == "Category Descriptions Blah blah");
Assert.IsNotNull(category, "Error: Category was not found.");
DeleteCategoryCommand command = mapper.Map<DeleteCategoryCommand>(category);
ICommandHandler<DeleteCategoryCommand> commandHandler = lifetime.Resolve<ICommandHandler<DeleteCategoryCommand>>();
ICommandResult result = commandBus.Submit(command, commandHandler);
Assert.IsNotNull(result, "Error: Category was not deleted by command bus");
Assert.IsTrue(result.Success, "Error: Category was not deleted by command bus.");
}
}
如您所见,类别实体映射到命令对象并通过命令总线传递给处理程序。在处理程序中,命令对象随后被转换回实体。此转换的映射配置文件忽略除 Id 之外的所有属性。
删除的通用存储库是:
public bool Delete(T entity) {
this.session.Delete(entity);
return true;
}
执行此方法时,我得到一个 NonUniqueObjectException。我有一个通用的 EntityBase,我的实体从中继承,并覆盖 Equals 和 GetHashCode 方法。在调试器中,我可以测试传递给 Delete 方法的实体与 NHibernate 会话缓存中的实体是否相等,并且它们的计算结果为真。当 Delete 方法在会话对象上执行时,它不会执行任何重写的 Equals 或 GetHashCode 方法。
如果 NHibernate 不使用 Equals 方法或 GetHashCode,谁能告诉我它如何检查缓存和比较对象?我修改了我的代码如下,但感觉像 hack。
public bool Delete(T entity) {
var id = entity.GetType().GetProperty("Id").GetValue(entity, null);
var sessionEntity = this.session.Load<T>(id);
var sessionEntityHashCode = sessionEntity.GetHashCode();
var entityHashCode = entity.GetHashCode();
if (!ReferenceEquals(null, sessionEntity)) {
this.session.Delete(sessionEntity);
} else {
this.session.Delete(entity);
}
return true;
}
事实证明这是一个范围界定问题。我不得不将代码更改为以下内容:
Category category = null;
using(var lifetime = container.BeginLifetimeScope()) {
ICategoryRepository categoryRepository = lifetime.Resolve<ICategoryRepository>();
DefaultCommandBus commandBus = lifetime.Resolve<DefaultCommandBus>();
IMappingEngine mapper = lifetime.Resolve<IMappingEngine>();
category = categoryRepository.Get(x => x.Title == "Updated Category Title");
Assert.IsNotNull(category, "Error: Category was not found.");
}
using(var lifetime = container.BeginLifetimeScope()) {
DefaultCommandBus commandBus = lifetime.Resolve<DefaultCommandBus>();
IMappingEngine mapper = lifetime.Resolve<IMappingEngine>();
DeleteCategoryCommand command = mapper.Map<DeleteCategoryCommand>(category);
ICommandHandler<DeleteCategoryCommand> commandHandler = lifetime.Resolve<ICommandHandler<DeleteCategoryCommand>>();
ICommandResult result = commandBus.Submit(command, commandHandler);
Assert.IsNotNull(result, "Error: Category was not deleted by command bus");
Assert.IsTrue(result.Success, "Error: Category was not deleted by command bus.");
}
TL;DR 版本是这样的:尝试在单元测试中删除实体时,我不断收到 NonUniqueObjectException。如果 NHibernate 不使用 Equals 方法或 GetHashCode,谁能告诉我它如何检查缓存和比较对象?
我有一个应用程序正在尝试使用以下代码进行测试。
[Test]
public void _04_Category_Delete_Test() {
using(var lifetime = container.BeginLifetimeScope()) {
ICategoryRepository categoryRepository = lifetime.Resolve<ICategoryRepository>();
DefaultCommandBus commandBus = lifetime.Resolve<DefaultCommandBus>();
IMappingEngine mapper = lifetime.Resolve<IMappingEngine>();
Category category = categoryRepository.Get(x => x.Title == "Category Descriptions Blah blah");
Assert.IsNotNull(category, "Error: Category was not found.");
DeleteCategoryCommand command = mapper.Map<DeleteCategoryCommand>(category);
ICommandHandler<DeleteCategoryCommand> commandHandler = lifetime.Resolve<ICommandHandler<DeleteCategoryCommand>>();
ICommandResult result = commandBus.Submit(command, commandHandler);
Assert.IsNotNull(result, "Error: Category was not deleted by command bus");
Assert.IsTrue(result.Success, "Error: Category was not deleted by command bus.");
}
}
如您所见,类别实体映射到命令对象并通过命令总线传递给处理程序。在处理程序中,命令对象随后被转换回实体。此转换的映射配置文件忽略除 Id 之外的所有属性。
删除的通用存储库是:
public bool Delete(T entity) {
this.session.Delete(entity);
return true;
}
执行此方法时,我得到一个 NonUniqueObjectException。我有一个通用的 EntityBase,我的实体从中继承,并覆盖 Equals 和 GetHashCode 方法。在调试器中,我可以测试传递给 Delete 方法的实体与 NHibernate 会话缓存中的实体是否相等,并且它们的计算结果为真。当 Delete 方法在会话对象上执行时,它不会执行任何重写的 Equals 或 GetHashCode 方法。
如果 NHibernate 不使用 Equals 方法或 GetHashCode,谁能告诉我它如何检查缓存和比较对象?我修改了我的代码如下,但感觉像 hack。
public bool Delete(T entity) {
var id = entity.GetType().GetProperty("Id").GetValue(entity, null);
var sessionEntity = this.session.Load<T>(id);
var sessionEntityHashCode = sessionEntity.GetHashCode();
var entityHashCode = entity.GetHashCode();
if (!ReferenceEquals(null, sessionEntity)) {
this.session.Delete(sessionEntity);
} else {
this.session.Delete(entity);
}
return true;
}
事实证明这是一个范围界定问题。我不得不将代码更改为以下内容:
Category category = null;
using(var lifetime = container.BeginLifetimeScope()) {
ICategoryRepository categoryRepository = lifetime.Resolve<ICategoryRepository>();
DefaultCommandBus commandBus = lifetime.Resolve<DefaultCommandBus>();
IMappingEngine mapper = lifetime.Resolve<IMappingEngine>();
category = categoryRepository.Get(x => x.Title == "Updated Category Title");
Assert.IsNotNull(category, "Error: Category was not found.");
}
using(var lifetime = container.BeginLifetimeScope()) {
DefaultCommandBus commandBus = lifetime.Resolve<DefaultCommandBus>();
IMappingEngine mapper = lifetime.Resolve<IMappingEngine>();
DeleteCategoryCommand command = mapper.Map<DeleteCategoryCommand>(category);
ICommandHandler<DeleteCategoryCommand> commandHandler = lifetime.Resolve<ICommandHandler<DeleteCategoryCommand>>();
ICommandResult result = commandBus.Submit(command, commandHandler);
Assert.IsNotNull(result, "Error: Category was not deleted by command bus");
Assert.IsTrue(result.Success, "Error: Category was not deleted by command bus.");
}