存储库和使用依赖注入的实体框架的工作单元模式

发布于 2024-10-27 04:35:55 字数 281 浏览 3 评论 0原文

我尝试了 http://efrepository.codeplex.com 中的 T4 模板,但我在 DI 上遇到困难(使用 StructureMap)示例代码。对于像我这样的 DI 初学者来说这还不够。它甚至无法编译。

我已经使用其非 DI 模板完成了一些示例项目。效果很好。我喜欢它生成所有必要的存储库,并且我可以轻松地自定义和扩展它们。但我无法让 DI 示例正常工作。有没有类似的项目(有更好的文档)?

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)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

流绪微梦 2024-11-03 04:35:55

我通常将以下设置与 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();
}

这里是一个考虑到 EF 的 ISession 实现:

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

就这样。这是大量的代码,但您几乎可以将其复制/粘贴到您的解决方案中,然后就可以开始了。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文