实体在创建后不会持久化
Entities are not persisted after creation
免责声明:这是我使用 NHibernate 的第一个项目,我可能会遗漏一些东西 "obvious"。
我的问题如下。我有一个创建订单的命令:
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
总是通过 returning true
.
不断否决插入内容
棘手的是,我 认为 此侦听器中的 return 值表示 success/failure 而它是为了表示否决权。
因此我不得不改为总是return false
,意思是无否决权。
免责声明:这是我使用 NHibernate 的第一个项目,我可能会遗漏一些东西 "obvious"。
我的问题如下。我有一个创建订单的命令:
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
总是通过 returning true
.
棘手的是,我 认为 此侦听器中的 return 值表示 success/failure 而它是为了表示否决权。
因此我不得不改为总是return false
,意思是无否决权。