Как сохранить сущность с бизнес-правилами? - PullRequest
0 голосов
/ 04 сентября 2018

Я использую ASP.NET Boilerplate для моего проекта. И у меня есть сущность, показанная во фрагменте кода ниже.

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 сущность, отсюда и причина моего наивного и, вероятно, неправильного подхода.

Пожалуйста, каков правильный подход к такой проблеме? Как мне сохранить состояния объекта, которые являются результатом вычислений или действий в пределах одного объекта?

1 Ответ

0 голосов
/ 04 сентября 2018

Вы можете выставить 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);
...