Как получить доступ к методу в контексте через единицу работы?
Если у меня есть следующий контекст:
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);
}
}
Теперь я реализую Единицу работы следующим образом:
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();
}
}
Я не знаю, как получить доступ к методу (хранимой процедуре) SEARCHEMPLOYEE
через UOW в моем коде.
Ответы
Ответ 1
Хорошо, в вашем случае вы просто добавили бы еще один "Прокси-метод" для этого метода в ваш класс HRCTX
proxy/UOW, или - поскольку HRCTX
предоставляет доступ к его базовому контексту - вызовите его непосредственно в контекст например:
HRCTX uow = new HRCTX(someContext);
uow.Context.SEARCHEMPLOYEE(123, "123");
Но я также хотел подчеркнуть, что DbContext
уже представляет шаблон Единицы работы (в сочетании с шаблоном репозитория, см. здесь). Вы в основном создаете прокси для своего контекста, который, насколько я вижу в этом примере, не добавляет никаких дополнительных преимуществ или функциональности, поэтому я бы предложил по крайней мере подумать о том, как напрямую использовать ваш HRMainDataCTX
и, возможно, избавиться от класс HRCTX
.
Ответ 2
Возможно, вам понадобится реализовать репозитории вместе с шаблоном Unit Of work, если вы хотите инкапсулировать свой DbContext и свою бизнес-логику. (Как указано в рекомендациях AspNet)
В общем случае ваша единица работы может обрабатывать репозитории следующим образом:
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;
}
}
Интерфейс и базовый класс ваших репозиториев:
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);
}
}
Теперь вы четко заключаете свою бизнес-логику:
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);
}
}
Затем вы можете использовать свой блок работы для доступа к бизнес-логике в режиме управляемого доменом.
HRCTX unitOfWork= new HRCTX(dbContext);
unitOfWork.GetNonGenericRepository<Employee, EmployeeRepository>().FindSpecific(1337,"1337");
Это может показаться слишком большим для того, что вы ожидали от ответа, но я думаю, что вам нужно структурировать приложение таким образом, если вы не хотите напрямую показывать вам DbContext/Dal.
Надеюсь, что это поможет!
Ответ 3
Эта веб-страница точно описывает, как достичь вашей цели.
http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application