Доступ к хранимым процедурам в сгенерированном коде DbContext с Entity Framework 4.1 с DDD - PullRequest
2 голосов
/ 01 октября 2011

Я работаю над большим проектом, использующим 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 вместо интерфейса?

1 Ответ

0 голосов
/ 02 октября 2011

То, что вы нашли, естественно. Проблема в том, что универсального репозитория недостаточно для реальных сценариев. Это хорошо только для «базовой» реализации. Вам нужен специальный репозиторий для сущности User, который будет предоставлять вызов переноса метода для контекстной хранимой процедуры.

...