【问题标题】:Should repositories use the same context instance within the Entity Framework 1.0存储库是否应该在 Entity Framework 1.0 中使用相同的上下文实例
【发布时间】:2010-06-22 23:29:49
【问题描述】:

我已经开始研究我正在做的一个项目的实体框架,并且正在通过存储库模式对它使用 BLL。据我了解,我应该为每个实体创建一个存储库,这样我就有了

public class UserRepository : IRepository<User>
{ ... }

public class AccountRepository : IRepository<Account>
{ ... }

在我看到的示例中,常见的做法是在 using 语句中创建实体上下文并在其中执行获取、更新和保存等操作。

using(var ctx = new AppEntities()
{
    //do whatever
    ctx.SaveChanges();
}

对于存储库的简单访问,这是可以的,但如果我想通过 BLL 在 2 个(或更多)存储库之间进行交互...

public void SaveSomethingMoreComplex()
{
    //BLL here stuff like validation etc

    _userRepository.GetSomeData();
    _accountRepository.SaveSomeData(account);
    _userRepository.SaveSomeMore(user);

    // Probably should have one final save that affects both repositories???
    // Should be in a transaction scope also?
}

最好为两个存储库使用相同的AppEntities 实例吗?

同样在这个例子中,最终保存可能应该在块的末尾,而不是像我的例子中的 2 和事务的一部分?

如果我确实使用了同一个实例,那么将其注入到存储库的构造函数中并让它在应用程序的生命周期中存在是否安全,或者是否有某些原因我看到的示例倾向于在一个单个方法调用?

感谢您提供的任何帮助。

【问题讨论】:

    标签: c# entity-framework .net-3.5 repository-pattern


    【解决方案1】:

    在处理存储库模式时,这实际上并不是一个不寻常的问题,它归结为提供一种显式管理工作单元生命周期的方法(在实体框架的情况下是你的上下文) .

    您没有指定您是在进行 Web 开发还是 Windows 开发,但在 Web 开发环境中,将工作单元的生命周期设置为单个请求的情况并不少见。因此,当您的请求开始时,您创建上下文,然后当它结束时,您可以调用 SaveChanges(或实体框架的任何名称),这会将更改应用于您在课程中搞砸的所有实体的请求。

    在 windows/service 上下文中,您可能希望为您的单元或工作设置某种明确的生命周期管理,因此您可以根据您正在做的事情定义 UoW 的范围。我倾向于使用 Conversation 比喻来包装 UoW 操作,这意味着我可以使用这样的东西:

    using(Conversation.Start())
    {
        // mess with the entities
    } // Dispose on the object returned from Start will 
      // Save Changes and close the session
    

    当然,这掩盖了其中的一些异常管理内容,您希望拥有这些内容,以便在发生故障时回滚更改。

    就实施而言,它有点取决于您的基础架构。我通常使用 IoC 容器,因此我将调用 Conversation.Start() 为我创建我的工作单元,并设置 IoC 以返回该特定实例,因此当我创建我的存储库时,它们会获得当前的 UoW。您还可以在对话上创建一些工厂方法,以便您可以从对话中获取您的存储库实例。有点取决于您希望使用的 API。

    希望这会有所帮助。

    【讨论】:

    • 我希望同时使用 BLL 和 DAL 层,但我先从 win 应用程序开始,看看效果如何。
    • 我还快速编写了一些类似于您的对话概念的代码(尽管我更喜欢对话这个词),其中可以包括事务管理。我肯定会尽可能使用 IoC。谢谢
    • 您应该能够在 winforms 和 ASP.Net 之间合理轻松地重用组件,这有点像 IRepository 的内容。只要您在 BLL 中为您使用的服务公开接口,您就应该处于良好状态。
    • 我已经按照您的方法将 IUnitOfWork 注入到可以获取当前上下文实例的存储库中。
    【解决方案2】:

    不,您不希望每个实体都有一个存储库。您希望将常用功能集分组到存储库类中。所有帐户功能都应该是一个存储库。这在 ASP.NET MVC 类型的应用程序中很常见,尽管我发现这在实践中并不是最好的。

    如果我要努力向存储库添加新功能,我稍后可能想要在实体本身上使用它,因此我创建包含此类业务逻辑的部分类。这样我就可以执行 ShoppingCart.AddProduct(int id) 之类的操作并在部分类中执行逻辑。

    另一个常见的场景是创建一次性视图模型。这实际上是我的偏好。

    http://blogs.msdn.com/b/dphill/archive/2009/01/31/the-viewmodel-pattern.aspx

    请记住,实体框架中的实体已经是数据源的抽象,或者可能与 LINQ To SQL 不同,后者是数据源的一对一映射。

    【讨论】:

    • 谢谢,我正在考虑将我的逻辑放在部分类中,但我可能想使用 WCF 和 DTO,因此在服务中包含更多的逻辑可能更合适。当我深入了解它时,我会看到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    • 1970-01-01
    相关资源
    最近更新 更多