草庐IT

c# - 试图简化我们的存储库模式

coder 2024-05-28 原文

目前我们已经在工作中实现了一个存储库模式。我们所有的存储库都位于它们自己的接口(interface)后面,并通过 Ninject 进行映射。我们的项目非常大,我试图解决的这个模式有几个怪癖。

首先,在某些 Controller 中,我们需要将 10 到 15 个存储库都放在同一个 Controller 中。当请求如此多的存储库时,构造函数变得相当丑陋。在您调用多个存储库上的方法后,第二个怪癖就会显现出来。在处理多个存储库后,我们需要调用 SaveChanges 方法,但是我们应该在哪个存储库上调用它呢?每个存储库都有一个。所有存储库都注入(inject)了相同的 Entity Framework 数据上下文实例,因此选择任何随机存储库来调用保存都可以。看起来很乱。

我查阅了“工作单元”模式并提出了一个我认为可以解决这两个问题的解决方案,但我对这个解决方案不是 100% 有信心。我创建了一个名为 DataBucket 的类。

// Slimmed down for readability
public class DataBucket
{
    private DataContext _dataContext;

    public IReportsRepository ReportRepository { get; set; }
    public IEmployeeRepository EmployeeRepository { get; set; }
    public IDashboardRepository DashboardRepository { get; set; }

    public DataBucket(DataContext dataContext,
        IReportsRepository reportsRepository,
        IEmployeeRepository employeeRepository,
        IDashboardRepository dashboardRepository)
    {
        _dataContext = dataContext;
        this.ReportRepository = reportsRepository;
        this.EmployeeRepository = employeeRepository;
        this.DashboardRepository = dashboardRepository;
    }

    public void SaveChanges()
    {
        _dataContext.SaveChanges();
    }
}

这似乎可以解决这两个问题。现在数据桶本身只有一个 SaveChanges 方法,您只需注入(inject)一个对象,即数据桶。然后,您可以将所有存储库作为属性访问。数据桶看起来会有点乱,因为它会在其构造函数中接受所有(很容易 50 个或更多)我们的存储库。

添加新存储库的过程现在包括:创建接口(interface)、创建存储库、在 Ninject 中映射接口(interface)和存储库,以及向数据桶添加属性并填充它。

我确实想到了一个替代方案,可以消除上面的一个步骤。

public class DataBucket
{
    private DataContext _dataContext;

    public IReportsRepository ReportRepository { get; set; }
    public IEmployeeRepository EmployeeRepository { get; set; }
    public IDashboardRepository DashboardRepository { get; set; }

    public DataBucket(DataContext dataContext)
    {
        _dataContext = dataContext;
        this.ReportRepository = new ReportsRepository(dataContext);
        this.EmployeeRepository = new EmployeeRepository(dataContext);
        this.DashboardRepository = new DashboardRepository(dataContext);
    }

    public void SaveChanges()
    {
        _dataContext.SaveChanges();
    }
}

这几乎消除了 Ninject 中的所有存储库映射,因为它们都在数据桶中实例化了。因此,现在添加新存储库的步骤包括:创建接口(interface)、创建存储库、将属性添加到数据桶并实例化。

你能看出这个模型有什么缺陷吗?从表面上看,以这种方式使用我们的存储库似乎更方便。这是以前解决过的问题吗?如果是这样,解决这个问题最常见和/或最有效的方法是什么?

最佳答案

First, there are some controllers where we need upwards of 10 to 15 repositories all in the same controller.

向抽象工厂模式问好。与其在 Ninject 中注册所有存储库并将它们注入(inject) Controller ,不如只注册工厂的单个实现,这将能够提供您需要的任何存储库——您甚至可以仅在 Controller 真正需要它们时才懒惰地创建它们。比将工厂注入(inject) Controller 。

是的,它也有一些缺点 - 您授予 Controller 权限以获取任何存储库。对你来说有问题吗?如果需要,您始终可以为某些子系统创建多个工厂,或者只需在单个实现上公开多个工厂接口(interface)。它仍然没有涵盖所有情况,但它比将 15 个参数传递给构造函数要好。顺便提一句。您确定不应该拆分这些 Controller 吗?

注意:这不是服务提供商反模式。

After doing work with multiple repositories we need to call the SaveChanges method, but which repository should we call it on?

向工作单元模式问好。工作单元是您应用程序中的逻辑事务。它将逻辑事务中的所有更改保存在一起。存储库不应负责持久更改 - 工作单元应该负责。有人提到 DbContext 是 Repository 模式的实现。 It is not .它是工作单元模式的实现,DbSet 是存储库模式的实现。

您需要的是保存上下文实例的中心类。上下文也将传递给存储库,因为它们需要它来检索数据,但只有中央类(工作单元)会提供保存更改。如果您需要更改隔离级别,它还可以处理数据库事务。

应该在哪里处理工作单元? That depends您的逻辑操作在这里被编排。如果操作直接在 Controller 的操作中编排,您还需要在操作中有工作单元,并在所有修改完成后调用 SaveChanges

如果您不太关心关注点分离,您甚至可以 combine unit of work and factory进入单类。这将我们带到您的 DataBucket

关于c# - 试图简化我们的存储库模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12097015/

有关c# - 试图简化我们的存储库模式的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  5. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  6. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  7. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  8. ruby-on-rails - environment.rb 中设置的常量在开发模式中消失 - 2

    了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl

  9. Ruby:标准递归模式 - 2

    我经常迷上ruby​​的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情

  10. ruby - 在 Ruby 中查找多个正则表达式匹配的模式和位置 - 2

    这应该是一个简单的问题,但我找不到任何相关信息。给定一个Ruby中的正则表达式,对于每个匹配项,我需要检索匹配的模式$1、$2,但我还需要匹配位置。我知道=~运算符为我提供了第一个匹配项的位置,而string.scan(/regex/)为我提供了所有匹配模式。如果可能,我需要在同一步骤中获得两个结果。 最佳答案 MatchDatastring.scan(regex)do$1#Patternatfirstposition$2#Patternatsecondposition$~.offset(1)#Startingandendingpo

随机推荐