【问题标题】:How do I wrap an EF 4.1 DbContext in a repository?如何在存储库中包装 EF 4.1 DbContext?
【发布时间】:2011-05-27 03:03:26
【问题描述】:

全部,

我需要将我的 EF 实现隐藏在存储库后面。我的简单问题:有没有办法在 DbSet 和 DbSet.Local 之间执行“查找”,而不必同时处理它们。

例如 - 我有标准的存储库实现,带有 Add/Update/Remove/FindById。我通过添加 FindByName 方法来打破通用模式(仅用于演示目的:)。这给了我以下代码:

客户端应用:

ProductCategoryRepository categoryRepository = new ProductCategoryRepository();
categoryRepository.Add(new ProductCategory { Name = "N" });
var category1 = categoryRepository.FindByName("N"); 

实施

public ProductCategory FindByName(string s)
{
    // Assume name is unique for demo
    return _legoContext.Categories.Where(c => c.Name == s).SingleOrDefault();
}

在本例中,category1 为空。

但是,如果我将 FindByName 方法实现为:

public ProductCategory FindByName(string s)
{
    var t = _legoContext.Categories.Local.Where(c => c.Name == s).SingleOrDefault();
    if (t == null)
    {
        t = _legoContext.Categories.Where(c => c.Name == s).SingleOrDefault();
    }
    return t;
}

在这种情况下,当查询一个新条目和一个仅在数据库中的条目时,我得到了我所期望的结果。但这提出了一些我感到困惑的问题:

1) 我会假设(作为存储库的用户)找不到下面的 cat2。但是找到了,很大一部分是cat2.Name是“Goober”。

ProductCategoryRepository categoryRepository = new ProductCategoryRepository();
var cat = categoryRepository.FindByName("Technic");
cat.Name = "Goober";
var cat2 = categoryRepository.FindByName("Technic");

2) 我想从我的存储库中返回一个通用的 IQueryable。

在存储库中包装对 DbSet 的调用似乎需要做很多工作。通常,这意味着我搞砸了。如有任何见解,我将不胜感激。

【问题讨论】:

    标签: repository entity-framework-4.1 iqueryable


    【解决方案1】:

    使用旧版本的 EF,您会遇到非常复杂的情况,由于需要引用,这些情况可能会很快出现。在这个版本中,我建议不要公开 IQueryable,而是公开 ICollections 或 IList。这将在您的存储库中包含 EF 并创建一个良好的分离。

    编辑:此外,通过发回 ICollection IEnumerable 或 IList,您可以限制和控制发送到数据库的查询。这也将允许您更轻松地微调和维护系统。通过公开 IQueriable,您将自己暴露于当人们向查询添加更多内容时发生的副作用,.Take() 或 .Where ....SelectMany,EF 将看到这些添加并生成 sql 以反映这些不受控制的查询。不限制查询可能会导致从 UI 执行查询,并且从长远来看是更复杂的测试和维护问题。

    因为存储库模式的重点是能够随意交换它们。应该完全隐藏 DbSet 的详细信息。

    我认为你的道路很好。我唯一可能问自己的是:

    上下文是否长期存在?如果没有,那么不要担心查询本地。已插入/删除的对象只有在提交后才能访问。

    如果这是一个长期存在的上下文并且您需要访问已删除和插入的对象,那么查询 Local 是一个好主意,但正如您所指出的,您可能会在某些时候遇到困难。

    【讨论】:

    • 感谢您的回答。我非常同意你的所有观点,但我一直遇到的一件事是告诉我的存储库的消费者。在我的工作地点进行的一项非常非正式的民意调查证实,用户希望能够在查询后取回新对象。有人告诉我“NHibernate 就是这样工作的”。我懒得自己确认。如果是这种情况,那么 ORM 的选择将在语义上泄漏到存储库的使用中。哦,好吧,这就是生活。再次感谢您的帮助。
    • @basilard99 查询后?如果保存上下文状态,则可以让 EF 从数据库中获取 id 和生成的数据并将该对象返回给调用方法。
    猜你喜欢
    • 2012-02-23
    • 2021-05-09
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    相关资源
    最近更新 更多