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?