Я работаю над большим проектом, использующим ASP.Net MVC 3, EF 4.1 и Ninject для внедрения зависимости.Я прочитал многие из существующих здесь вопросов, касающихся DDD, EF и шаблона репозитория, но я не могу найти никого, кто бы включал хранимые процедуры в эти шаблоны.
Мне не нравится идея реализацииеще один шаблон хранилища поверх того, что уже кажется UnitOfWork / RepositoryPattern, уже определенным с помощью DbContext.Кроме того, мне вообще не нравится идея создания классов Service и Repository для каждого типа сущностей в системе, если это возможно.
Источник моей проблемы проистекает из этого общего интерфейса репозитория, который, кажется, все используют.
public interface IRepository<TEntity> where TEntity : class
{
TEntity Get(Expression<Func<TEntity, bool>> whereClause);
IEnumerable<TEntity> List();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> whereClause);
void Add(TEntity entity);
void Delete(TEntity entity);
// And so on...
}
Это здорово, если все ваши запросы могут быть в контексте одной сущности.Когда это ломается для меня, это когда я хочу получить доступ к хранимой процедуре.С EF 4.1 и Code Generatrion вы можете добавлять хранимые процедуры (например, SelectUser), и он будет генерировать контекст, который выглядит примерно так:
namespace MyCompany.Data.Database
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using MyCompany.Domain.Entities;
using MyCompany.Domain.Contracts;
public partial class MyCompanyEntities : DbContext
{
public MyCompanyEntities()
: base("name=MyCompanyEntities")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<Order> Orders { get; set; }
public DbSet<User> Users { get; set; }
public virtual ObjectResult<User> SelectUser(Nullable<int> userId)
{
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(User).Assembly);
var userIdParameter = userId.HasValue ?
new ObjectParameter("UserId", userId) :
new ObjectParameter("UserId", typeof(int)); MyCompanyEntities x; x.
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<User>("SelectUser", userIdParameter);
}
public virtual ObjectResult<User> SelectUser(Nullable<int> userId, MergeOption mergeOption)
{
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(User).Assembly);
var userIdParameter = userId.HasValue ?
new ObjectParameter("UserId", userId) :
new ObjectParameter("UserId", typeof(int));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<User>("SelectUser", mergeOption, userIdParameter);
}
}
}
В рамках моей настройки DDD у меня есть класс UserService, и я быкак «внедрить» хранилище в его конструктор.Многие примеры предполагают, что конструктор должен принимать (IRepository userRepository).Это не работает для меня.Хранимые процедуры генерируются в классе DbContext как метод, и я не могу его увидеть.
Единственное, о чем я могу думать, - это создать другой интерфейс с методами хранимых процедур.Я действительно не хочу добавлять его в универсальный IRepository, потому что тогда, когда у вас есть экземпляр IRepository , вы все равно увидите SelectUser, который кажется немного странным.Может быть, это не имеет большого значения?
Возможно, я поступаю об этом неправильно.Не стоит ли мне беспокоиться о создании интерфейса поверх моего DbContext, если я не пытаюсь создать совершенно новый шаблон репозитория?Я действительно создавал это для внедрения зависимости.Было бы неправильно, если бы конструктор UserService использовал экземпляр MyCompanyEntities вместо интерфейса?