Шаблон репозитория и единицы работы для Entity Framework с использованием внедрения зависимостей - PullRequest
1 голос
/ 28 марта 2011

Я попробовал T4-Template из http://efrepository.codeplex.com,, но я борюсь с примером кода DI (использует StructureMap). Это просто недостаточно для начинающего DI, как я. Он даже не компилируется.

Я уже сделал несколько примеров проектов с использованием шаблона без DI. И это сработало отлично. Мне нравится, что он генерирует все необходимые репозитории и что я могу легко настроить и расширить их. Но я не могу заставить примеры DI работать. Есть ли похожие проекты (с лучшими документами)?

1 Ответ

2 голосов
/ 24 июня 2011

Я обычно использую следующую настройку с картой структуры конца EF: (приготовьтесь, куча кода появится).

Это базовый интерфейс, который мы будем использовать для внедрения наших контроллеров:

public interface ISession : IDisposable
{
    void CommitChanges();
    void Delete<T>(Expression<Func<T, bool>> expression) where T : class, new();
    void Delete<T>(T item) where T : class, new();
    void DeleteAll<T>() where T : class, new();
    T Single<T>(Expression<Func<T, bool>> expression) where T : class, new();
    IQueryable<T> All<T>() where T : class, new();
    void Add<T>(T item) where T : class, new();
    void Add<T>(IEnumerable<T> items) where T : class, new();
    void Update<T>(T item) where T : class, new();
}

А здесь ISession реализация с учетом EF:

public class EntityFrameworkSession : ISession 
{
    // MyContext is a class inheriting from EF's DbContext
    readonly DbContext _context;

    public EntityFrameworkSession(DbContext context)
    {
        _context = context;
    }

    public void CommitChanges()
    {
        _context.SaveChanges();
    }

    public void Delete<T>(Expression<Func<T, bool>> expression) 
        where T : class, new()
    {
        var query = All<T>().Where(expression);
        foreach (var item in query)
        {
            Delete(item);
        }
    }

    public void Delete<T>(T item) where T : class, new()
    {
        _context.Set<T>().Remove(item);
    }

    public void DeleteAll<T>() where T : class, new()
    {
        var query = All<T>();
        foreach (var item in query)
        {
            Delete(item);
        }
    }

    public void Dispose()
    {
        _context.Dispose();
    }

    public T Single<T>(Expression<Func<T, bool>> expression) 
        where T : class, new()
    {
        return All<T>().FirstOrDefault(expression);
    }

    public IQueryable<T> All<T>() where T : class, new()
    {
        return _context.Set<T>().AsQueryable();
    }

    public void Add<T>(T item) where T : class, new()
    {
        _context.Set<T>().Add(item);
    }
    public void Add<T>(IEnumerable<T> items) where T : class, new()
    {
        foreach (var item in items)
        {
            Add(item);
        }
    }
    public void Update<T>(T item) where T : class, new()
    {
        //nothing needed here
    }
}

Теперь эта реализация ISession не очень удобна для внедрения, потому что, хотя она и хороша и универсальна, она не имеет конструктора по умолчанию, поэтому способ ее решения - написать небольшую оболочку, которая предоставляет только параметр- меньше конструктор:

/// <summary>
/// This is the EF site alternative
/// </summary>
public class SiteEFSession : EntityFrameworkSession
{
    public SiteEFSession() : base(new MyContext())
    { }
}

Теперь мы можем легко ввести его. Мы настроили его в StructureMap следующим образом:

ObjectFactory.Initialize(x =>
{
    x.For<ISession>().Use<SiteEFSession>();
});

А если у вас есть, например, контроллер стиля MVC:

public class HomeController : Controller
{
   private readonly ISession _session;

   // ISession will be injected automatically
   public HomeController(ISession session)
   {
       _session = session;
   }
}

Вот, пожалуйста. Это чертовски много кода, но вы можете в значительной степени скопировать / вставить его в свое решение, и вы должны быть в порядке.

...