存储库使用依赖注入的实体框架的工作模式单位 [英] Repository & Unit of Work Pattern for Entity Framework using Dependency Injection

查看:167
本文介绍了存储库使用依赖注入的实体框架的工作模式单位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 http://efrepository.codeplex.com 尝试了T4模板,但我正在努力与DI(使用StructureMap)示例代码。对于像我这样的DI初学者来说,这还不够它甚至不编译。



我已经用非DI模板完成了一些示例项目。而且它表现出色。我爱,它生成所有必要的存储库,我可以轻松地自定义和扩展它们。但我不能让DI示例工作。有没有类似的项目(更好的文档)?

解决方案

我通常使用EF端结构图进行以下设置:(大括号, / p>

这是我们用来注入控制器的基本界面:

  public interface ISession:IDisposable 
{
void CommitChanges();
void Delete< T>(Expression< Func< T,bool>>表达式)其中T:class,new();
void Delete< T>(T item)其中T:class,new();
void DeleteAll< T>()其中T:class,new();
T Single< T>(表达式< Func< T,bool>>表达式)其中T:class,new();
IQueryable< T>所有< T>()其中T:class,new();
void Add< T>(T item)其中T:class,new();
void添加< T>(IEnumerable< T>项)其中T:class,new();
void Update< T>(T item)其中T:class,new();
}

这里一个 ISession

  public class EntityFrameworkSession:ISession 
{
// MyContext是一个从EF的DbContext继承的类
只读DbContext _context;

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

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

public void Delete< T>(Expression< Func< T,bool>>>表达式)
其中T:class,new()
{
var query = All< T>()。Where(expression);
foreach(查询中的var项)
{
删除(item);
}
}

public void Delete< T>(T item)其中T:class,new()
{
_context.Set&T ;()。除去项目);
}

public void DeleteAll< T>()其中T:class,new()
{
var query = All< T>
foreach(查询中的var项)
{
删除(item);
}
}

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

public T Single< T>(Expression< Func< T,bool>>>表达式)
其中T:class,new()
{
return All< T>()。FirstOrDefault(expression);
}

public IQueryable< T>所有< T>()其中T:class,new()
{
return _context.Set&T;()。AsQueryable();
}

public void Add< T>(T item)其中T:class,new()
{
_context.Set (项目);
}
public void添加< T>(IEnumerable< T>项目)其中T:class,new()
{
foreach(项目中的项目)
{
Add(item);
}
}
public void Update< T>(T item)其中T:class,new()
{
//这里不需要
}
}

现在这个 ISession 实现不是非常方便的注入,因为虽然很好,通用,它没有一个默认的构造函数,所以解决它的方法是写一个小的封装,只暴露一个无参数的构造函数:

  ///< summary> 
///这是EF网站的替代方案
///< / summary>
public class SiteEFSession:EntityFrameworkSession
{
public SiteEFSession():base(new MyContext())
{}
}

现在我们可以很容易地注入它。我们在 StructureMap 中设置如下:

  ObjectFactory.Initialize x => 
{
x.For< ISession>()。使用< SiteEFSession>();
});

如果你有一个MVC风格的控制器:

  public class HomeController:Controller 
{
private readonly ISession _session;

// ISession将自动注入
public HomeController(ISession session)
{
_session = session;
}
}

你去了。这是一个helluva的代码,但你可以将它复制/粘贴到您的解决方案中,您应该很好去。


I tried the T4-Template from http://efrepository.codeplex.com, but I'm struggling with the DI (uses StructureMap) Example code. It's just not enough for a DI beginner like me. It doesn't even compile.

I already have done a few sample projects with its Non-DI Template. And it worked out great. I love, that it generates all necessary repositories and that I can easily customize and extend them. But I can't get the DI Examples working. Are there any similar projects (with better docs)?

解决方案

I normally use the following setup with EF end Structure map: (brace yourself, bunch o' code coming up).

This is the base interface we'll use to inject our controllers:

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();
}

And here an ISession implementation with EF in mind:

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
    }
}

Now this ISession implementation is not very handy to inject because, while being nice and generic, it doesn't have a default constructor, so the way to solve it is by writing a small wrapper that only exposes a parameter-less constructor:

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

Now we can easily inject it. We set it up in StructureMap as follows:

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

And if you have, for instance, an MVC style controller:

public class HomeController : Controller
{
   private readonly ISession _session;

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

There you go. It's a helluva lot of code but you can pretty much copy/paste it into your solution and you should be good to go.

这篇关于存储库使用依赖注入的实体框架的工作模式单位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆