【问题标题】:How to persist entity with business rules?如何用业务规则持久化实体?
【发布时间】:2018-09-04 07:36:05
【问题描述】:

我在我的项目中使用ASP.NET Boilerplate。我有一个实体,如下面的代码 sn-p 所示。

public class Transaction : FullAuditedEntity<Guid>, IMustHaveTenant
{
    protected Transaction()
    {
        TransactionState = TransactionState.Uncompleted;
    }

    public TransactionState TransactionState { get; protected set; }
    public virtual Loan Loan { get; protected set; }
    public int TenantId { get; set; }
    // ...

    public async Task CompleteAsync(ICoreBankingService coreBankingService, IRepository<Transaction, Guid> transactionRepository)
    {
        try
        {
            // Perform a series of compulsory actions in some given sequence with coreBankingService that might throw exception
            Loan.SetSomeStuffThatOriginatedFromMotherTransaction();
            TransactionState = TransactionState.Completed;
        }
        catch (Exception ex)
        {
            // Log the exception and set this Transaction entity state appropriately
            TransactionState = TransactionState.Failed;
        }
        finally
        {
            // Make sure by all means to persist the resulting the entity within itself
            await transactionRepository.UpdateAsync(this);
        }
    }
}

我知道我应该将持久性与实体分开(顺便说一下,这是由ASP.NET Boilerplate 提供的开箱即用的架构!使用Application Services)。

但是,我需要确保我使用coreBankingService按照给定顺序执行一系列强制操作,并在这些计算的每个阶段持续更改Transaction 实体,因此是我幼稚且可能是错误方法的原因。

请问,解决此类问题的正确方法是什么?如何持久化由同一实体内的计算或操作产生的实体状态?

【问题讨论】:

    标签: c# entity-framework asp.net-core domain-driven-design aspnetboilerplate


    【解决方案1】:

    你可以暴露internal改变状态的方法:

    public class Transaction : FullAuditedEntity<Guid>, IMustHaveTenant
    {
        protected Transaction()
        {
            TransactionState = TransactionState.Uncompleted;
        }
    
        public TransactionState TransactionState { get; protected set; }
        public virtual Loan Loan { get; protected set; }
        // ...
    
        internal void Abort()
        {
            TransactionState = TransactionState.Failed;
        }
    
        internal void Complete()
        {
            TransactionState = TransactionState.Completed;
        }
    }
    

    并在同一个程序集中定义域服务:

    public class TransactionManager : DomainService
    {
        private readonly ICoreBankingService _coreBankingService;
        private readonly LoanManager _loanManager;
        private readonly IRepository<Transaction, Guid> _transactionRepository;
    
        public TransactionManager(
            ICoreBankingService coreBankingService,
            LoanManager loanManager,
            IRepository<Transaction, Guid> transactionRepository)
        {
            _coreBankingService = coreBankingService;
            _loanManager = loanManager;
            _transactionRepository = transactionRepository;
        }
    
        public async Task TryCompleteAsync(Transaction transaction)
        {
            try
            {
                // Use _coreBankingService to do something that might throw exception
                _coreBankingService.DoSomething();
                _loanManager.SetSomeStuffThatOriginatedFromMotherTransaction(transaction.Loan);
                transaction.Complete();
            }
            catch (Exception ex)
            {
                // Log the exception and abort the Transaction
                transaction.Abort();
            }
            finally
            {
                // Make sure by all means to persist the resulting the entity
                await _transactionRepository.UpdateAsync(transaction);
            }
       }
    }
    

    用法:

    await _transactionManager.TryCompleteAsync(transaction);
    

    【讨论】:

    • 这正是我想要的!有时,对于像我这样的新手程序员来说,思考解决问题的正确方法/架构可能非常具有挑战性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    • 2015-11-15
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多