If I have the following Context :
public partial class HRMainDataCTX : DbContext { public HRMainDataCTX() : base("name=HRMainDataCTX") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { throw new UnintentionalCodeFirstException(); } //DbSets public virtual int SEARCHEMPLOYEE(Nullable<decimal> p_EMP_NUM, string p_EMP_NAME) { var p_EMP_NUMParameter = p_EMP_NUM.HasValue ? new ObjectParameter("P_EMP_NUM", p_EMP_NUM) : new ObjectParameter("P_EMP_NUM", typeof(decimal)); var p_EMP_NAMEParameter = p_EMP_NAME != null ? new ObjectParameter("P_EMP_NAME", p_EMP_NAME) : new ObjectParameter("P_EMP_NAME", typeof(string)); return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("SEARCHEMPLOYEE", p_EMP_NUMParameter, p_EMP_NAMEParameter); } }
Now i implement Unit of work like this :
public class HRCTX : IDisposable { private readonly HRMainDataCTX _context; public HRCTX() { _context = new HRMainDataCTX(); } public HRCTX(HRMainDataCTX context) { _context = context; } public int Save() { return _context.SaveChanges(); } public HRMainDataCTX Context { get { return _context; } } public void Dispose() { _context.Dispose(); } }
I don't know how to access the method (stored procedure) SEARCHEMPLOYEE
through UOW in my code behind.
3 Answers
Answers 1
Well, in your case you would simply add another "Proxy-Method" for this method to your HRCTX
proxy / UOW class, or - since HRCTX
provides access to its underlying context - call it directly on the context like this:
HRCTX uow = new HRCTX(someContext); uow.Context.SEARCHEMPLOYEE(123, "123");
But I also wanted to emphasize that the DbContext
already represents a Unit of Work pattern (combined with a Repository pattern, see here). You are basically creating a proxy for your context, which - as far as I can see in this example - adds no further benefits or functionality, so I'd suggest to at least think about directly using your HRMainDataCTX
and possibly getting rid of the HRCTX
class.
Answers 2
You may need to implement repositories along with your Unit Of work pattern if you want to encapsulate your DbContext and your business logic. (As suggested in the AspNet guidelines)
In a generic manner, your unit of work can handle repositories like this:
public class HRCTX : IDisposable { private readonly HRMainDataCTX _context; private Dictionary<Type, object> Repositories { get; set; } public HRCTX() { _context = new HRMainDataCTX(); this.Repositories = new Dictionary<Type, object>(); } //Get and add a repository to the dictionary if ot does not exist public IRepository<TEntity> GetNonGenericRepository<TEntity, TRepository>() where TEntity : class { if (this.Repositories.Keys.Contains(typeof(TRepository))) { return this.Repositories[typeof(TRepository)] as IRepository<TEntity>; } var repoType = typeof(TRepository); var constructorInfo = repoType.GetConstructor(new Type[] { typeof(DbContext)}); IRepository<TEntity> repository = (IRepository<TEntity>) constructorInfo.Invoke(new object[] { this._context}); this.Repositories.Add(typeof(TRepository), repository); return repository; } public IRepository<TEntity> GetGenericRepository<TEntity>() where TEntity : class { if (this.Repositories.Keys.Contains(typeof(TEntity))) { return this.Repositories[typeof(TEntity)] as IRepository<TEntity>; } IRepository<TEntity> repository = new Repository<TEntity>(this._context); this.Repositories.Add(typeof(TEntity), repository); return repository; } }
The interface and base class of your repositories:
public interface IRepository<TEntity> where TEntity : class { TEntity Find(Expression<Func<TEntity, bool>> match); } public class Repository<TEntity> : IRepository<TEntity> where TEntity : class { protected DbContext Context { get; set; } public Repository(DbContext context) { this.Context = context; } public TEntity Find(Expression<Func<TEntity, bool>> match) { return Context.Set<TEntity>().SingleOrDefault(match); } }
Now is the part where you clearly encapsulate your business logic:
public class EmployeeRepository : Repository<Employee> { public EmployeeRepository(DbContext context) : base(context) { } public override Employee Find(Expression<Func<TEntity, bool>> match) { // You can either use the base class method or implement your custom logic } //This is where you encapsulate your business logic public Employee FindSpecific(Nullable<decimal> employeeNum, string employeeName){ return this.Context.SEARCHEMPLOYEE(employeeNum, employeeName); } }
Then you can use your Unit Of Work to access you business logic in a domain driven design way.
HRCTX unitOfWork= new HRCTX(dbContext); unitOfWork.GetNonGenericRepository<Employee, EmployeeRepository>().FindSpecific(1337,"1337");
It can seem to be too much for what you expected as an answer but I think you need to structure your application that way if you don't want to expose you DbContext / Dal directly.
Hope it helps !
Answers 3
This webpage documents exactly how to accomplish your goal.
0 comments:
Post a Comment