C# 如何在EF中使用存储过程和使用存储库模式的复杂类型?

C# 如何在EF中使用存储过程和使用存储库模式的复杂类型?,c#,entity-framework,repository,repository-pattern,C#,Entity Framework,Repository,Repository Pattern,在实体框架中处理存储库模式时,我们如何使用存储过程和复杂类型?请任何人给出一个简单的例子 另外,在什么情况下,我们实际上应该使用存储库模式 提前感谢存储库模式对于将数据存储机制与应用程序分离非常重要。通过这样做,您可以更容易地在以后进行单元测试或替换数据结构。阅读我的博客文章,了解我是如何/为什么在这里这样做的: 就我个人而言,我不再使用存储过程,因为在大多数情况下,我并不认为有必要使用存储过程,但是为了使用我的存储库模式实现这一点,我建议您创建一个新的RepositoryDataSource来

在实体框架中处理存储库模式时,我们如何使用存储过程和复杂类型?请任何人给出一个简单的例子

另外,在什么情况下,我们实际上应该使用存储库模式


提前感谢

存储库模式对于将数据存储机制与应用程序分离非常重要。通过这样做,您可以更容易地在以后进行单元测试或替换数据结构。阅读我的博客文章,了解我是如何/为什么在这里这样做的:

就我个人而言,我不再使用存储过程,因为在大多数情况下,我并不认为有必要使用存储过程,但是为了使用我的存储库模式实现这一点,我建议您创建一个新的RepositoryDataSource来映射到存储过程,然后通过EF或老式SQL调用存储过程。我建议在更新或保存时抛出某种异常

==编辑(回答“为什么有两层”的问题)==

我选择使用两个层的原因是因为在我看来,存储库既与您如何获取数据(数据源层)有关,也与您如何呈现该层有关(在我的实现中,可能是名称不正确的存储库)。通过将实现一分为二,如何在任何情况下都保持不变。相反地,如果您想改变如何做,同时保持与what的松散耦合

例如,您可能希望将EF数据源交换为内存版本。这不一定会改变数据呈现给应用程序的方式

另一方面,您可能希望缓存数据或预捕获日志,以记录有关写入数据存储的性能的一些信息。为什么封面下使用的实际存储机制很重要


就我个人而言,我发现在这个特殊的地方进行了拆分,使解决方案更加灵活。

我认为您忽略了一点,即为什么人们在EF已经通过ObjectSet/DbSet实现存储库模式的情况下实现了存储库模式

流行的答案是,许多教程建议您在没有正当理由的情况下使用它。有正当理由不在ObjectSet/DbSet上使用存储库层。不过,我会指出一些理由,说明为何这样做较为可取

默认过滤器 在实际应用程序中,有许多情况需要默认过滤器。例如,停产产品不出售。如果直接公开产品ObjectSet/DbSet,如果有人忘记应用默认筛选器,则会出现问题。它还避免了逻辑的重复。您也可以在以后修改默认过滤器,而不破坏问题

public IQueriable<Product> GetAll()
{
    return context.Products.Where(p => !p.IsDiscontinued);
}
只读实体 在许多情况下,其他应用程序负责创建、删除和更新实体,而您的应用程序只显示实体。但是ObjectSet/DbSet在这种情况下公开了不受支持的功能。在这种情况下,另一个好处是使用
NoTracking
选项来减少实体物化时间

在不公开实现的情况下切换数据访问有时LINQ不够。在这里,您可以使用原始SQL或SPs。当EF公开的功能不足时,拥有存储库将避免公开不同的查询/更新方法

使用现有数据库 当您无法创建EF能够处理的数据库时。现有表可能有
Sql Variant
XML
列。将条目复制到另一个表和无数其他需要处理以保持数据库完整性的情况


这些技术可能不是防弹的,但在情况需要时会派上用场。我的建议是,在不直接跳到存储库的情况下,您最好考虑添加另一个实现所需功能所必需的抽象层

EF不是已经对您的存储进行了抽象了吗?你为什么还要再把它包起来?您在存储库中具体做了哪些单元测试?@estebanarya-您通常不会对存储库进行单元测试(您需要对它们进行集成测试)。通过注入存储库接口,您可以模拟该接口来独立于数据库对其他类(业务逻辑)进行单元测试。模拟可以返回测试所需的任何POCO集合。EF是一个抽象,提供对象映射、实体/更改跟踪。存储库包装用于访问数据的业务逻辑。@Eranga的回答中描述了类似逻辑的问题。i、 e查询产品,但不包括停产产品。通过使用存储库模式,您可以确保在访问底层数据时始终遵循业务规则。@EstebanAraya这实际上是一个很好的问题,许多存储库实现只有一个层。我修改了答案,解释了这一点
public void Delete(Product product)
{
    // can apply any other logic here
    product.IsDeleted = true;
}