Recentemente ho letto su unità di lavoro e modelli di progettazione del deposito; lavorare con EF chiedendomi se questo è un buon modello di design

0

Mi sono ritrovato a creare record figlio che richiedono l'esistenza di un record master, in primo luogo, in modo che possano fare riferimento alla chiave primaria del record master (se è il termine giusto).

Per fare ciò usando EF 6 ho provato a chiamare SaveChanges() due volte - una volta per creare il master record in modo che la sua chiave di identità venga generata e una volta dopo che i bambini sono stati creati.

Il problema che ho riscontrato è che EF non gradisce più chiamate a SaveChanges() , quindi ho dovuto utilizzare una transazione. Non mi piace usare una transazione perché mi sembra un po 'disordinata per qualche motivo che non riesco ad articolare.

Per me è un problema un po 'comune doverlo fare così, invece di using , try/catch e commit/rollback ho pensato che sarebbe stato più facile avere questo ogni volta:

this._dbContextWrapper.CommitIfTrue(() =>
{
    // Multiple calls to SaveChanges() here

    return true;
});

Pur avendo esposto BeginTransaction() sul mio _dbContextWrapper in modo che se passare un Func<bool> non sia desiderabile.

public interface IRepository
{
    IQueryable<TModel> Query<TModel>()
        where TModel : class;

    TModel Find<TModel>(params object[] key)
        where TModel : class;

    void Add<TModel>(TModel model)
        where TModel : class;

    void Update<TModel>(TModel updated, params object[] key) 
        where TModel : class;

    IDataResult SaveChanges();

    void Delete<TModel>(params object[] key)
        where TModel : class;

    IRepositoryTransaction BeginTransaction();

    IRepositoryTransaction BeginTransaction(IsolationLevel isolationLevel);

    IDataResult CommitIfTrue(Func<bool> transaction);

    IDataResult CommitIfTrue(Func<bool> transaction, IsolationLevel isolationLevel);
}

public interface IRepositoryTransaction : IDisposable
{  
    void Commit();

    void Rollback();
}

public interface IDataResult
{
    bool IsSuccess { get; }

    string ErrorMessage { get; }
}

Mi rendo conto che questo " IRepository " è solo un sottile involucro intorno a DbContext - Lo sto facendo in modo che le mie classi possano avere un'implementazione di Mock fornita a loro invece di dover incasinare con Fakes a aggirare l'aspetto non virtuale dei metodi di DbContext .

La mia domanda è:

Il mio metodo CommitIfTrue è ragionevole? C'è un modo per fare qualcosa di simile che sia anche più testabile / non coinvolga Action s o Func s?

    
posta Words Like Jared 31.07.2014 - 01:36
fonte

1 risposta

1

Non so perché sarebbe necessario restituire true. Perché non potrebbe semplicemente commettere se non viene lanciata alcuna eccezione? Così sarebbe se avessi una transazione in un'istruzione using . Esistono argomenti a favore e contro il controllo esterno e interno di questi tipi di cose (es. Iterazione esterna vs interna), ma non vedo la necessità di avere ENTRAMBI CommitIfTrue() e BeginTransaction() . In sostanza forniscono la stessa funzionalità.

    
risposta data 31.07.2014 - 03:05
fonte

Leggi altre domande sui tag