Действительно впечатлен курсом двойного назначения Juile Lerman на тему «EF in Enterprise» и решил создать мое демо-приложение.Нужна помощь в применении принципов SOLID
Я использую VS 2012 и последние версии EF, SQL Server и MVC. Я создаю демо-приложение, которое применяет принципы SOLID. Я делаю это, чтобы лучше понять, как реализовать DI & модульное тестирование.
Я использовал первый подход DB для этого демонстрационного приложения. Он содержит только одну таблицу с именем UserDetails и ниже, как выглядит на SQL-сервере. Я буду использовать эту таблицу для операций CRUD.
Ниже, как я слоистый мое заявление:
1. WESModel Решение: Этот слой содержит мой файл Model1.edmx и класс контекста, как показано ниже.
namespace WESModel
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using WESDomain;
public partial class WESMVCEntities : DbContext
{
public WESMVCEntities()
: base("name=WESMVCEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<UserDetail> UserDetails { get; set; }
}
}
2. WESDomain Решение: Этот слой содержит мои классы домен (или классы POCO). Эти классы POCO были автоматически созданы на моем уровне WESModel. Я переместил их на этот слой. Вот как выглядит один класс POCO.
namespace WESDomain
{
using System;
using System.Collections.Generic;
public partial class UserDetail:IUserDetail
{
public int Id { get; set; }
public string UserName { get; set; }
}
}
3: WESDataLayer Решение: Этот слой содержит ссылки на библиотеки DLL из моих выше 2-х слоев. Этот уровень имеет мой класс репозитория, как показано ниже. На данный момент, я держу в IRepository в том же классе :)
namespace WESDataLayer
{
public class UserDetailRepository : IUserDetailRepository
{
WESMVCEntities context = new WESMVCEntities();
public IQueryable<IUserDetail> All
{
get { return context.UserDetails; }
}
public IQueryable<IUserDetail> AllIncluding(params Expression<Func<IUserDetail, object>>[] includeProperties)
{
IQueryable<IUserDetail> query = context.UserDetails;
foreach (var includeProperty in includeProperties) {
query = query.Include(includeProperty);
}
return query;
}
public IUserDetail Find(int id)
{
return context.UserDetails.Find(id);
}
public void InsertOrUpdate(UserDetail userdetail)
{
if (userdetail.Id == default(int)) {
// New entity
context.UserDetails.Add(userdetail);
} else {
// Existing entity
context.Entry(userdetail).State = EntityState.Modified;
}
}
public void Delete(int id)
{
var userdetail = context.UserDetails.Find(id);
context.UserDetails.Remove(userdetail);
}
public void Save()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public interface IUserDetailRepository : IDisposable
{
IQueryable<IUserDetail> All { get; }
IQueryable<IUserDetail> AllIncluding(params Expression<Func<UserDetail, object>>[] includeProperties);
UserDetail Find(int id);
void InsertOrUpdate(UserDetail userdetail);
void Delete(int id);
void Save();
}
}
4: ConsoleApplication1 Решение: Это мой слой UI. Это будет мое приложение MVC в моем конечном приложении. Здесь я просто запрашиваю DB и отображаю данные. Так выглядит код.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
IUserDetailRepository repo = new UserDetailRepository();
var count = repo.All.ToList().Count().ToString();
Console.WriteLine("Count: {0}", count);
Console.ReadLine();
}
}
}
Вопрос: Мой слой UI не имеет реф к EF DLL. Однако он имеет экземпляр класса репозитория. В приложении MVC мой контроллер будет иметь экземпляр класса репозитория или UnitOfWork.
a) Правильно ли это делать?
б) Есть ли способ, чтобы я мог абстрагировать его?
c) Что делать, если в будущем я хочу поменять EF на Dapper или любой другой инструмент ORM?
d) Как я могу поместить свой инструмент DI в этот проект? В каком слое это должно быть?
e) Тестирование устройства. Я знаю StructureMap и хочу использовать его в этом проекте таким образом, чтобы в будущем я смог поменять его на Ninject. Как мне это достичь?
Спасибо, что прочитали этот большой вопрос, и я очень признателен, если кто-нибудь может указать мне в правильном направлении.
'IRepository' не должен возвращать типы' IQueryable'. Пожалуйста, [см. Эту ссылку] (https://stackoverflow.com/questions/33755499/entity-framework-repository-pattern-why-not-return-iqueryable) – StepUp