【问题标题】:Some issues about Rob Conery's repository pattern关于 Rob Conery 的存储库模式的一些问题
【发布时间】:2010-02-16 10:12:49
【问题描述】:

请在阅读答案后阅读我在问题末尾的更新:

我正在尝试应用存储库模式 如Rob Conery's described on his blog 在“MVC 店面”下。 但是我想问一些问题 在我应用这个设计之前我有 模式。

Rob 制作了自己的“模型”并使用了一些 ORM“LINQ to SQL or Entity Framework (EF)”将他的数据库映射到 实体。

然后他使用自定义存储库 给出IQueryable<myModel> 和 他制作的这些存储库 在 ORM Entities 和他的 Model 类之间映射或“解析”。

我在这里问什么:

是否可以在 ORM Entities 和我的 模型“classes”并仅加载 我想要的属性?我希望 重点很清楚。

POCO 更新

**

这是我在多次建议和尝试后做出的决定:

**

毕竟,就 Rob Conery 先生的意见而言,我有更好的解决方案:

  1. 我将模型构建为“POCOs”并将它们放在“模型层”中,因此它们与“edmx”文件无关。
  2. 构建我的存储库来处理这个依赖于“DbContext”的“POCO”模型
  3. 然后我创建了一个“ViewModels”来从这些存储库中获取视图所需的信息。

所以我确实不需要需要在“EF 模型”和“我的模型”之间再添加一层。我只是稍微扭曲我的模型并强制 EF 处理它。

在我看来,这种模式比 Rob Conery 的模式要好。

【问题讨论】:

  • 您是关心从表中加载所有数据还是从表的单行中加载所有列?无论哪种情况,无论存储库模式如何,都有一些方法可以加载您想要的内容。
  • 这就是上帝发明视图模型和 AutoMapper 的原因。您不应该将模型中的所有内容都返回到您的视图中……那只是糟糕的设计。你在这里谈论两件不同的事情......你在谈论数据访问和在视图上显示数据。这些应该分开保存。存储库模式非常适合 DI 到您的控制器中......我强烈推荐它,因为它很简单。

标签: asp.net-mvc entity-framework orm repository-pattern poco


【解决方案1】:

是的,如果您使用的是 LINQ to SQL,这是可能的。您需要做的就是使用投影将您想要的数据提取到您选择的对象中。您不需要使用接口和诸如此类的所有这些装饰 - 如果您使用特定于视图的模型(听起来像是您需要的) - 创建一个 ViewModel 类。

我们称之为 ProductSummaryView:

public class ProductSummaryView{
   public string Name {get;set;}
   public decimal Price {get;set;}
}

现在从存储库中加载它:

var products= from p in _repository.GetAllProducts
              where p.Price > 100
              select new ProductSummaryView {
                  Name=p.ProductName,
                  Price=p.Price

              }

这将提取价格 > 100 的所有产品并返回 IQueryable。此外,由于您只要求两列,因此在 SQL 调用中将只指定两列。

【讨论】:

  • 非常感谢 Rob 先生的回答。更好奇的是,这个 ViewModel 类应该在我的模型类库中,并直接使用 L2S 来填充它,而不是使用我的存储库。我对吗 ??。再次非常感谢
  • 您的 ViewModel 应该带有 UI 位 - 而不是模型。这是一种“自适应”模式,可帮助 Web 应用处理模型数据 - 您希望将其保留在使用的地方。
【解决方案2】:

不要回避您的问题,但最终由您决定存储库的工作方式。

高级前提是您的控制器将指向某个存储库接口,例如 IRepository<T> where T : IProduct。它的实现可以做很多事情——从磁盘加载整个数据库并存储在内存中,然后解析 LINQ 表达式以返回内容。或者它可以只返回一组固定的虚拟数据用于测试目的。因为您正在处理存储库接口,所以您可以拥有任意数量的具体实现。

现在,如果您正在寻找对 Rob 特定实现的批评,我不确定这是否与 StackOverflow 密切相关。

【讨论】:

  • 顺便说一句——重新阅读您的帖子,我强烈建议您不要遵循仅根据上下文加载对象属性的子集的模式。这是一个假的延迟加载,并且由于该对象被传递到不同的上下文,它非常容易出错。如果必须,请考虑一个基类和派生类,一个具有较小的属性子集,而另一个具有完整的详细信息。
  • 感谢您的建议以及我将要执行的操作,但实际上我正在尝试找到更简单的方法 ;) 再次感谢。
【解决方案3】:

虽然可以使用查询(与存储库模式无关)基于对该对象的列子集的查询来填充对象的一部分,但这并不是“通常”完成的方式。

如果你想返回一个对象的子集,你通常会创建一个只包含该属性子集的新类。这通常(在 MVC 世界视图中)被称为 View Model 类。然后,您使用投影查询来填充该新类。

无论您是否使用存储库模式,您都可以完成所有这些操作。我认为这两个概念之间没有冲突的重叠。

【讨论】:

  • 好的,我用刚需要的属性创建了一个新类,但我将从我的自定义存储库中填充这个类,它将加载 L2S 类中的所有数据并将它们填充到我的模型类中,然后我会得到我想要的财产。这就是 Rob 的存储库模式中发生的事情。但我依赖于 L2S 课程,我可以选择我想要的,但这会导致我分解我的层。
【解决方案4】:

延迟加载

请记住,IQueryable 会将所有加载推迟到最后一个负责任的时刻。您可能不必使用 LINQ 运算符加载所有数据来获取所需的数据。 ; )

尊重视图中域类的依赖关系,我会说不。为此使用 ViewModel 模式。它更易于维护;您可以使用AutoMapper 来避免映射问题,它们在复合视图场景中非常灵活:)

根据新问题...答案是肯定的,你可以。正如 Rob Conery 所说,使用投影; ):

var query = from p in DataContext.Persons}
select new Persons
{
  firstname = p.firstname,
  lastname = p.lastname
});

【讨论】:

    猜你喜欢
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 2021-06-08
    • 1970-01-01
    相关资源
    最近更新 更多