c# - 实体在创建后不会持久化
问题描述
免责声明:这是我第一个使用 NHibernate 的项目,我可能会错过一些“明显”的东西。
我的问题如下。我有一个创建订单的命令:
public void Handle(BuyOneProductCommand command)
{
var product = _uow.Query<Product>().Single(p => p.Name == command.ProductName);
var order = new Order(product, 1);
_uow.SaveOrUpdate(order);
_uow.Commit();
}
该命令接收一个新创建的UnitOfWork
. 但是,在Commit()
我的更改从未持久化到数据库之后,也没有抛出异常。任何想法为什么?
命令
public class Order : AggregateRoot
{
public virtual Product Product { get; }
public virtual int Quantity { get; }
public virtual DateTime Date { get; }
public Order(Product product, int quantity) : this()
{
Product = product;
Quantity = quantity;
Date = DateTime.Now;
AddDomainEvent(new OrderCreatedEvent(this));
}
protected Order() { }
}
订单地图
public class OrderMap : ClassMap<Order>
{
public OrderMap()
{
Id(x => x.Id);
References(o => o.Product);
Map(x => x.Quantity);
Map(x => x.Date);
}
}
工作单位
public sealed class UnitOfWork : IUnitOfWork
{
private readonly ISession _session;
private readonly ITransaction _transaction;
private bool _isAlive = true;
public UnitOfWork()
{
_session = SessionFactory.OpenSession();
_transaction = _session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public void Commit()
{
if (!_isAlive)
return;
try
{
_transaction.Commit();
}
finally
{
_isAlive = false;
_transaction.Dispose();
_session.Dispose();
}
}
public T Get<T>(long id) where T : class
{
return _session.Get<T>(id);
}
public void SaveOrUpdate<T>(T entity)
{
_session.SaveOrUpdate(entity);
}
public IQueryable<T> Query<T>()
{
return _session.Query<T>();
}
}
会话工厂
public static class SessionFactory
{
private static ISessionFactory _factory;
public static void Init(string connectionString)
{
_factory = BuildSessionFactory(connectionString);
}
public static ISession OpenSession()
{
return _factory.OpenSession();
}
private static ISessionFactory BuildSessionFactory(string connectionString)
{
return Fluently.Configure()
.Database(SQLiteConfiguration.Standard.ConnectionString(connectionString).ShowSql())
.Mappings(m => m.FluentMappings
.AddFromAssembly(Assembly.GetExecutingAssembly())
.Conventions.Add(
ForeignKey.EndsWith("Id"),
ConventionBuilder.Property.When(criteria => criteria.Expect(x => x.Nullable, Is.Not.Set), x => x.Not.Nullable()))
.Conventions.Add<OtherConventions>()
.Conventions.Add<IncrementConvention>()
)
.ExposeConfiguration(x =>
{
x.EventListeners.PreUpdateEventListeners = new IPreUpdateEventListener[] { new DomainEventsListener() };
x.EventListeners.PreInsertEventListeners = new IPreInsertEventListener[] { new DomainEventsListener() };
x.EventListeners.PreDeleteEventListeners = new IPreDeleteEventListener[] { new DomainEventsListener() };
x.EventListeners.PreCollectionUpdateEventListeners = new IPreCollectionUpdateEventListener[] { new DomainEventsListener() };
x.EventListeners.PostCommitUpdateEventListeners = new IPostUpdateEventListener[] { new IntegrationEventsListener() };
x.EventListeners.PostCommitInsertEventListeners = new IPostInsertEventListener[] { new IntegrationEventsListener() };
x.EventListeners.PostCommitDeleteEventListeners = new IPostDeleteEventListener[] { new IntegrationEventsListener() };
x.EventListeners.PostCollectionUpdateEventListeners = new IPostCollectionUpdateEventListener[] { new IntegrationEventsListener() };
new SchemaUpdate(x).Execute(true, true);
})
.BuildSessionFactory();
}
private class OtherConventions : IHasManyConvention, IReferenceConvention
{
public void Apply(IOneToManyCollectionInstance instance)
{
instance.LazyLoad();
instance.AsBag();
instance.Cascade.SaveUpdate();
instance.Inverse();
}
public void Apply(IManyToOneInstance instance)
{
instance.LazyLoad(Laziness.Proxy);
instance.Cascade.None();
instance.Not.Nullable();
}
}
private class IncrementConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
instance.Column("Id");
instance.GeneratedBy.Increment();
}
}
}
IPreInsertEventListener
public bool OnPreInsert(PreInsertEvent @event)
{
var aggregateRoot = @event.Entity as AggregateRoot;
if (aggregateRoot == null)
return true;
foreach (IEvent domainEvent in aggregateRoot.DomainEvents)
{
DomainEvents.Dispatch(domainEvent);
}
aggregateRoot.ClearDomainEvents();
return true;
}
解决方案
正如 Roman Artiukhin 指出的那样,我IPreInsertEventListener
总是通过返回来不断否决插入true
。
棘手的是,我认为这个监听器的返回值是表示成功/失败,而它是表示否决。
因此我不得不改变为总是返回false
,这意味着没有否决权。
推荐阅读
- hugo - HUGO 将相对 URLS 转换为绝对 URL
- java - univocity - 如何从选定的字符中解析字符串
- ruby-on-rails - 在rails 5中用户删除帐户(before_destroy)后发送电子邮件
- scheduled-tasks - 多实例环境下的 ScheduledExecutorService 冗余
- excel - Excel 数据透视表 - 提取数据透视表列表并用分号连接
- javascript - Angular 10 - Openlayers 获取地图坐标(点击)
- java - 调用包存储过程时超出的最大游标数
- php - 来自 div 和 p 的模态输入变量
- c# - 使用c#在switch case中检查变量的字符串值
- javascript - 仅来自顶部的 MouseOut 事件