I’ve started to work on a single user c# winforms application, with EF6 db first approach, AutoMapper, Generic Repository and UnitOfWork. They have been previously implemented by others former colleagues . I’m not very experienced with those concepts but I have read a lot of links.
The main issue is now that the single user c# app needs to be updated for multiuser environment. Using the current implementation , the external changes(like update operations) performed on database are not visible inside de controller.
I’ve tried using _unitOfWork.Context.Refresh(System.Data.Entity.Core.Objects.RefreshMode.StoreWins, _tableRepository.FindAllInContext()); to refresh the context but I think this is not a good option, because if I try to update a table column value after refresh, the action will not be saved in database.
public interface IDbEntity
{
int Id { get; set; }
bool IsDeleted { get; set; }
}
public interface IRepository<T, T1>
where T : class, IDbEntity
where T1 : class, IDbEntity
{
int Add(T1 newEntityViewModel);
void AddRange(List<T1> newEntities);
void Remove(int id);
void RemoveFromDb(int id);
List<T1> Find(Expression<Func<T1, bool>> predicate);
T1 FindById(int id);
List<T1> FindAll();
T FindByIdInContext(int id);
int GetNextId();
List<T> FindAllInContext();
}
internal class DbRepository<T, T1> : IRepository<T, T1>
where T : class, IDbEntity
where T1 : class, IDbEntity
{
protected ObjectSet<T> _objectSet;
protected List<T1> _internalList;
protected ObjectContext _context;
public DbRepository(ObjectContext context)
{
try
{
_internalList = new List<T1>();
_objectSet = context.CreateObjectSet<T>();
_context = context;
}
catch (Exception ex)
{
log.Error(ex.Message);
throw;
}
}
public int Add(T1 newEntityViewModel)
{
try
{
var entityDto = AutoMapperConfiguration.GetMapperConfiguration().Map<T1, T>(newEntityViewModel);
_objectSet.AddObject(entityDto);
_context.SaveChanges();
//check id
return entityDto.Id;
}
catch (Exception ex)
{
log.Error(ex.Message);
throw;
}
}
public List<T1> Find(Expression<Func<T1, bool>> predicate)
{
try
{
var listT1 = AutoMapperConfiguration.GetMapperConfiguration().Map<List<T1>>(_objectSet.Where(q => !q.IsDeleted));
var result = listT1.Where(predicate.Compile()).ToList();
return result;
}
catch (Exception ex)
{
log.Error(ex.Message);
throw;
}
}
public List<T1> FindAll()
{
try
{
var listT1 = AutoMapperConfiguration.GetMapperConfiguration().Map<List<T1>>(_objectSet.Where(q => !q.IsDeleted));
return listT1;
}
catch (Exception ex)
{
log.Error(ex.Message);
throw;
}
}
}
public interface IUnitOfWork
{
IRepository<User, User_ViewModel> Users { get; }
IRepository<Type, Type_ViewModel> Types { get; }
/// and a lot more repositories
ObjectContext Context { get; }
void Commit();
}
internal class DbUnitOfWork : IUnitOfWork
{
private DbRepository<User, User_ViewModel> _users = null;
private DbRepository<Type, Type_ViewModel> _types = null;
private readonly ObjectContext _context;
private readonly EntityConnection _connectionString;
public ObjectContext Context { get { return _context; } }
public DbUnitOfWork(EntityConnection connectionString)
{
try
{
_connectionString = connectionString;
_context = new ObjectContext(connectionString, true);
_context.ContextOptions.LazyLoadingEnabled = true;
}
catch (Exception ex)
{
log.Error(ex.Message);
throw;
}
}
public IRepository<User, User_ViewModel> Users
{
get
{
return _users ?? (_users = new DbRepository<User, User_ViewModel>(_context));
}
}
public IRepository<Type, Type_ViewModel> Types
{
get
{
return _types ?? (_types = new DbRepository<Type, Type_ViewModel>(_context));
}
}
public void Commit()
{
try
{
_context.SaveChanges();
}
catch (Exception ex)
{
log.Error(ex.Message);
throw;
}
}
}
DbController.cs
public partial class DbController
{
protected readonly IUnitOfWork _unitOfWork;
protected readonly IRepository<User, User_ViewModel> _userRepository;
protected readonly IRepository<Type, Type_ViewModel> _typeRepository;
public SafeIOController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_userRepository = _unitOfWork.Users;
_typeRepository = _unitOfWork.Types;
}
public void Save()
{
_unitOfWork.Commit();
}
}
Controller_User.cs
public partial class DbController
{
public List<User_ViewModel> GetAllUsers()
{
try
{
return _userRepository.FindAll();
}
catch (Exception ex)
{
_exHandler.LogErrorMessage(Constants_Exception.DB_EXCEPTION_MSG, ex, _exHandler.GetCurrentMethod());
throw;
}
}
}
and then in winforms app
_unitOfWork = new DbUnitOfWork(connectionString);
_controller = new DbController(_unitOfWork);
How can I properly implement unitOfWork in order to have the latest information from db inside my context?