Я обычно использую следующую настройку с картой структуры конца 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;
}
}
Вот, пожалуйста. Это чертовски много кода, но вы можете в значительной степени скопировать / вставить его в свое решение, и вы должны быть в порядке.