首页 > 解决方案 > 实体在创建后不会持久化

问题描述

免责声明:这是我第一个使用 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;
}

标签: c#sqlitenhibernate

解决方案


正如 Roman Artiukhin 指出的那样,我IPreInsertEventListener总是通过返回来不断否决插入true

棘手的是,我认为这个监听器的返回值是表示成功/失败,而它是表示否决

因此我不得不改变为总是返回false,这意味着没有否决权


推荐阅读