ASP.NET MVC, EntityFramework, DBContext, репозиторий в другом проекте

В настоящее время я работаю над проектом ASP.NET MVC 5, и я стараюсь отполировать архитектуру проекта; сделать так же просто и просто, чтобы люди могли работать над ним в будущем, насколько это возможно.

Для начала я переместил модели EntityFramework (включая IdentityUser и AccountViewModel) в проект библиотеки классов в рамках одного и того же решения. На данный момент это основной проект MVC.

Однако теперь я размышляю над созданием нового проекта уровня доступа к данным, который будет содержать DbContext (или DbContexts, если я решаю использовать несколько DbContext), а также уровень доступа к данным. Каков наилучший способ сделать это?

Этот проект DAL будет ссылаться на проект модели, а основной проект MVC будет ссылаться только на проект DAL.

После чтения этой статьи! Мне было интересно, действительно ли шаблон репозитория действительно устарел при использовании EntityFramework.

Итак, мои два основных вопроса:

1) Каков наилучший способ вытащить DAL в отдельный проект

2) Каков наилучший способ доступа к содержимому базы данных с помощью EF

Ответ 1

Ваш вопрос довольно широк. Например, что вы подразумеваете под "лучшим способом доступа к содержимому базы данных с помощью EF"? Лучший способ с точки зрения производительности?

Я попытаюсь ответить, предоставив вариант, который я предпочитаю (из которого я в основном использую какой-то вариант), который использует шаблон репозитория. Если вы будете использовать свои EF-наборы непосредственно в качестве репозитория, вы можете утверждать, что вам не нужен шаблон репозитория, но мне нравится обернуть их в один из моих собственных.

Так как я не могу понять, что вы имеете в виду наилучшим образом, я дам свои личные предпочтения, которые будут соответствовать типичному веб-проекту.

Я не буду публиковать весь код, чтобы он был полностью функциональным, но вы должны получить четкое представление о том, что происходит.

Настройка (4 проекта):

UI ---------- > Domain.Logic(w. Domain.Models) ----------------- > Данные (сохранение контекста EF).

Данные:

public partial class EFContextContainer : DbContext 
enter code here
public EFContextContainer ()
        : base("name=EFContextContainer")
    {
    }

public DbSet<IdentityUser> IdentityUsers { get;set; } 

С оболочкой, возвращающей контекст:

public static class Database
{
    public static EFContextContainerGetContext()
    {
        return new EFContextContainer();
    }

}

У вас может быть такая настройка репозитория:

Интерфейс:

public interface IRepository<T> where T : class
{
    IQueryable<T> GetAll();
    T GetById(Guid id);
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
    void Delete(Guid id);
}

Реализация (для краткости реализована только функция добавления (T)):

public class EFRepository<T> : IRepository<T>, IDisposable where T : class
{
    public EFRepository(DbContext dbContext)
    {
        if (dbContext == null)
            throw new ArgumentNullException("dbContext");
        DbContext = dbContext;
        DbSet = DbContext.Set<T>();

    }

    protected DbContext DbContext { get; set; }

    protected DbSet<T> DbSet { get; set; }

    public virtual void Add(T entity)
    {
        DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
        if (dbEntityEntry.State != EntityState.Detached)
        {
            dbEntityEntry.State = EntityState.Added;
        }
        else
        {
            DbSet.Add(entity);
        }
    }

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

}

Домен:

Domain.Logic(IdentityUserManager будет классом в Domain.Models):

public class IdentityUserManager
{
    public void Add(IdentityUser idUser)
    {
        using(var idUserRepository = new EFRepository<IdentityUser>(Database.GetContext())
        {
            idUserRepository.Add(idUser);
        }
    }
}

интерфейс:

[HttpPost]
public ActionResult Post(UserViewModel model)
{
    UserIdentity user = MapUser(model);
    var userManager = new IdentityUserManager();
    userManager.Add(user);

    return View(new UserViewModel());
}

(Это не все, что написано в Visual Studio, поэтому пропустите любые орфографические ошибки.)

Признавая, в этом коде может быть намного больше абстракции, но было бы смешно записывать здесь полное решение. Например, вы можете использовать шаблон Unit of Work, который отлично работает с шаблоном репозитория. Поэтому прочитайте этот пример, а не полный справочник о том, как реализовать эту настройку. Вещи могут быть установлены намного чище, чем этот пример.

Для углубленного представления о реализации некоторых из этих шаблонов я настоятельно рекомендую вам взглянуть на курс отдельных приложений для страниц от John Papa on Plural Достопримечательность. Он отлично справляется с объяснением преимуществ этих моделей и способов их реализации.