Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何减少代码中的SQL查询量?_C#_Sql Server_Ado.net_Query Optimization_Data Access - Fatal编程技术网

C# 如何减少代码中的SQL查询量?

C# 如何减少代码中的SQL查询量?,c#,sql-server,ado.net,query-optimization,data-access,C#,Sql Server,Ado.net,Query Optimization,Data Access,我正在编写一个与MS-SQL Server数据库通信的大型C应用程序 随着应用程序越来越大,我发现自己编写了越来越多的样板代码,其中包含各种类和表单中的各种SQL查询,如下所示: using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Windows.Forms; public class SomeForm : Form {

我正在编写一个与MS-SQL Server数据库通信的大型C应用程序

随着应用程序越来越大,我发现自己编写了越来越多的样板代码,其中包含各种类和表单中的各种SQL查询,如下所示:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;

public class SomeForm : Form
{
    public void LoadData(int ticketId)
    {
        // some multi-table SQL select and join query
        string sqlQuery = @"
            SELECT TOP(1) [Foo].Id AS FooId, [Foo].Name AS FooName, [Foo].Address AS FooAddress
                        [Bar].Name AS BarName, [Bar].UnitPrice AS BarPrice,
                        [Bif].Plop
            FROM        [dbo].[Foo]
            INNER JOIN  [dbo].[Bar]
            ON          [Bar].Id = [Foo].BarId
            INNER JOIN  [dbo].[Bif]
            ON          [Bar].BifId = [Bif].Id
            WHERE       [Foo].TicketId = @ticketId";

        SqlCommand sqlCmd = new SqlCommand();
        sqlCmd.CommandText = sqlQuery;
        sqlCmd.Parameters.AddWithValue("@ticketId", ticketId);

        // connection string params etc and connection open/close handled by this call below
        DataTable resultsDataTable = SqlQueryHelper.ExecuteSqlReadCommand(sqlCmd);

        if (resultsDataTable.Rows.Count > 0)
        {
            var row = resultsDataTable.Rows[0];

            // read-out the fields
            int fooId = 0;
            if (!row.IsNull("FooId"))
                fooId = row.Field<int>("FooId");

            string fooName = "";
            if (!row.IsNull("FooName"))
                fooName = row.Field<string>("FooName");

            // read out further fields...

            // display in form
            this.fooNameTextBox.Text = fooName;
            // etc.
        }
    }
}
这个项目中有几十个表单,它们在概念上做着相同的事情,只是选择了不同的SQL查询、不同的列等等。 每次打开表单时,都会不断地查询数据库

对于本地DB服务器来说,速度还可以,但在速度较慢的VPN上使用应用程序是痛苦的

有没有更好的方法来减少查询数据库的数量?是否在内存中缓存数据库并对内存中的数据执行查询

在我的项目中,我已经向数据源添加了一些数据表,但我不明白如何进行上面提到的复杂查询

有更好的方法吗


谢谢各位的建议

我可以提出几点建议:

不必使用switch-to,在这里您可以使用/newer-version并使用简单的C语言编写查询,而不用担心查询SQL。 使用存储过程、SQL函数、视图-写在SQL Server数据库中,这些调用由SQL Server缓存,从而提供更高效的执行、安全性和更高的可维护性。 为了使查询更有效地对抗数据库表,请考虑使用那些在过滤操作中更经常使用的数据,如搜索。 在您的C中使用模式,包括与实体框架代码的集成,这些代码实际上可以完成您想要的事情,即收集多个SQL查询并将它们一次发送给SQL Server执行,而不是逐个发送查询。这不仅会大大提高性能,而且会使编码尽可能简单。 注意:查询的问题之一不仅与执行有关,而且与每次需要执行特定查询时打开和关闭SQL数据库连接有关。使用存储库和工作单元设计模式方法解决了这个问题

根据您的业务需要,使用或缓存数据,这会对许多用户重复。
我可以提出几点建议:

不必使用switch-to,在这里您可以使用/newer-version并使用简单的C语言编写查询,而不用担心查询SQL。 使用存储过程、SQL函数、视图-写在SQL Server数据库中,这些调用由SQL Server缓存,从而提供更高效的执行、安全性和更高的可维护性。 为了使查询更有效地对抗数据库表,请考虑使用那些在过滤操作中更经常使用的数据,如搜索。 在您的C中使用模式,包括与实体框架代码的集成,这些代码实际上可以完成您想要的事情,即收集多个SQL查询并将它们一次发送给SQL Server执行,而不是逐个发送查询。这不仅会大大提高性能,而且会使编码尽可能简单。 注意:查询的问题之一不仅与执行有关,而且与每次需要执行特定查询时打开和关闭SQL数据库连接有关。使用存储库和工作单元设计模式方法解决了这个问题

根据您的业务需要,使用或缓存数据,这会对许多用户重复。
除了实体框架,还有另一种解决方案

例如,您可以使用

它是一个商业产品,但它不仅映射实体框架等数据库对象,而且还基于层创建完整的存储库

在我看来,如果你愿意付钱的话,它比EF好

实体框架有一些缺点。例如,存储库将在整个层中泄漏


因为您需要在实体的所有使用者上引用实体框架。。。因此,即使您的体系结构看起来正确,在运行时您仍然可以从上层执行sql查询,即使是在不知不觉中。

除了实体框架之外,还有另一种解决方案

例如,您可以使用

它是一个商业产品,但它不仅映射实体框架等数据库对象,而且还基于层创建完整的存储库

在我看来,如果你愿意付钱的话,它比EF好

实体框架有一些缺点。例如,存储库将在整个层中泄漏


因为您需要在实体的所有使用者上引用实体框架。。。因此,即使您的体系结构看起来是正确的,在运行时,您仍然可以从上层执行sql查询,即使是在不知情的情况下。

我不认为建议使用fram 访问数据集的工作将解决您的问题。问题不在于编写SQL或LINQ查询。您必须始终在某个时刻向数据库或数据集发送查询

问题是从何处查询数据库。 你关于在不同的类和表单中编写包含各种SQL查询的代码的声明让我感到寒心。我最近在一家公司工作,他们也做了同样的事情。因此,他们无法再维护自己的数据库。维护仍然是可能的,但只是基本的,非常昂贵/耗时,非常令人沮丧-因此没有人喜欢这样做,因此没有人这样做,结果它变得越来越糟。查询速度越来越慢,唯一可能的快速修复方法是为数据库服务器购买更多带宽

实际查询分散在所有项目中,因此无法改进/重构查询并识别它们或改进表设计。但最糟糕的是,他们无法切换到更快或更便宜的数据库模型,例如图形结构的数据库,尽管他们迫切需要这样做。这会让你在顾客面前显得邋遢。在这样的环境中工作完全没有乐趣,所以我离开了。听起来很糟糕

您确实应该将数据库和SQL与业务代码分离。所有这些都应隐藏在接口后面:

IRepository repository = Factory.GetRepository();

// IRepository exposes query methods, which hide 
// the actual query and the database related code details from the repository client or business logic
var customers = repository.GetCustomers();
在你的项目中传播这段代码并没有坏处。它将提高可维护性和可读性。它将数据持久性与实际业务逻辑分离,因为您隐藏/封装了所有细节,如实际数据库、查询和查询语言。如果要切换到另一个数据库,只需实现一个新的IRepository来修改现有查询。更改数据库不会中断应用程序

所有查询都在一个位置/层中实现。当谈到查询时,这也包括LINQ查询,这就是为什么使用像实体框架这样的框架不能解决您的问题。您可以使用依赖项注入或工厂模式来分发IRepository的实现。这甚至允许在运行时在不同的数据库之间切换,而无需重新编译应用程序

使用此模式存储库模式还允许将Entitiy Framework等框架与业务逻辑分离

看看存储库模式。如果还不算太晚,你应该开始重构你现有的代码。如果保持原样,价格太高了

关于缓存,我知道数据库或DBMS已经非常有效地处理了数据缓存。你能做的就是

本地缓存数据,例如,如果数据不会远程更改,因为 其他一些客户端将对其进行修改,例如本地客户端设置。这 可以显著减少网络流量的方法。 本地缓存数据,例如,如果您经常访问此数据集,并且远程更改不太可能发生或将产生影响。您可以定期更新本地数据存储或使其无效,例如,在一段时间后,强制客户端发送新查询以更新缓存。 您还可以使用LINQ在本地过滤数据。这也可能降低成本 网络流量,尽管您最终可能会读取更多数据 必需的此外,过滤通常由 数据库管理系统。 可以考虑升级数据库服务器或VPN来增加。 带宽。 索引还将显著缩短查找时间。 您应该考虑重构所有SQL查询。有很多 有关如何提高SQL查询性能的文章。你的方式 建立查询将对性能或性能产生重大影响 执行时间,尤其是大数据。 您可以使用数据虚拟化。当您只能向用户显示其中的20条记录时,从数据库中提取数千条记录是没有意义的。当用户滚动视图时拉取更多数据。或者更好的是,显示预先选择的列表,例如最近的项目,并允许用户搜索感兴趣的数据。这样,您只读取用户明确要求的数据。这将大大提高总体性能,因为用户通常只对很少的记录感兴趣。 在引入接口依赖倒置之前 下面的示例旨在说明,这是一个架构或设计问题,而不是框架或库的问题。 库或框架可以在不同的层次上提供帮助,但不能解决这个问题,这是通过将特定于环境的查询散布到所有业务代码中引入的。查询应始终保持中立。查看业务代码时,您不应该知道数据是从文件还是数据库中获取的。此详细信息必须隐藏或封装

当您在整个业务代码中传播实际的数据库访问代码时,无论是直接使用纯SQL还是借助框架,您都无法 在没有连接数据库的情况下编写单元测试。这是不可取的。这会使测试变得过于复杂,并且测试的执行速度会非常慢。您希望测试您的业务逻辑,而不是数据库。这是单独的测试。您通常希望模拟数据库

问题是: 您需要在应用程序模型或业务逻辑的多个位置从数据库中获取数据

最直观的方法是,无论何时何地需要数据,都可以调度数据库查询。这意味着,当数据库是Postgre数据库时,所有代码当然都会使用PostgreSQL或其他框架,如实体框架或ORM。如果您决定将数据库或DBMS更改为某个Oracle,或希望使用不同的框架来管理实体,您将被迫接触并重写使用PostgreSQL或实体框架的所有代码

在一个大的商业应用程序中,这将是迫使你的公司保持现有状态并让你的团队梦想一个更美好的世界的原因。挫折感会上升。维护与数据库相关的代码几乎是不可能的,容易出错且耗时。由于实际的数据库访问不是集中的,重写与数据库相关的代码意味着在整个应用程序中爬行。最糟糕的情况是毫无意义的SQL查询字符串的传播,没有人理解或记住。不可能移动到新数据库或重构查询以提高性能,而不会占用宝贵且昂贵的时间和团队资源

以下简化符号方法在应用程序的业务逻辑中以某种形式重复,可能访问不同的实体并使用不同的过滤器,但使用相同的查询语言、框架或库。假设我们发现类似的代码一千次:

private IEnumerable GetCustomers()
{
  // Use Entity Framework to manage the database directly
  return DbContext.Customers;
}
由于框架深入到我们的业务代码中,因此我们引入了一种与框架的紧密耦合。代码知道如何管理数据库。它知道实体框架,因为它必须在任何地方使用它的类或API。 事实证明,如果您想用其他框架替换实体框架,或者只是想放弃实体框架,那么您必须在数千个地方重构代码——在应用程序中使用此框架的任何地方

在引入接口依赖倒置并封装所有数据库访问之后 依赖倒置将通过引入接口来帮助消除对具体类的依赖。由于在使用帮助器框架或普通SQL方言时,我们更喜欢组件和类之间的松散耦合,以增强灵活性、可测试性和可维护性,因此我们必须包装此特定代码并将其隐藏在接口存储库模式后面

我们现在引入了接口方法,例如GetHighPriorityCustomers和GetAllCustomers,而不是使用数据库框架或SQL或LINQ查询来读取、写入或过滤数据的上千个位置。如何提供数据或从哪种数据库获取数据是详细信息,只有该接口的实现知道

现在,应用程序不再直接使用任何特定于框架或数据库的语言:

interface IRepository
{
  IEnumerable<Customer> GetHighPriorityCustomers();
  IEnumerable<Customer> GetAllCustomers();
}
IRepository的实施:

现在,您决定用Microsoft SQL替换MySQL。您所要做的就是实现一个新的IRepository。 您可以在不影响原始业务逻辑的情况下交换任何数据库、更改查询语言或引入帮助器框架。一旦被写入,就再也不会涉及数据库的更改。
如果将实现移动到单独的程序集,甚至可以在运行时交换它们。

我认为使用框架访问数据集之类的建议都不会解决您的问题。问题不在于编写SQL或LINQ查询。您必须始终在某个时刻向数据库或数据集发送查询

问题是从何处查询数据库。 你关于在不同的类和表单中编写包含各种SQL查询的代码的声明让我感到寒心。我最近在一家公司工作,他们也做了同样的事情。因此,他们无法再维护自己的数据库。维护仍然是可能的,但只是基本的,非常昂贵/耗时,非常令人沮丧-因此没有人喜欢这样做,因此没有人这样做,结果它变得越来越糟。查询速度越来越慢,唯一可能的快速修复方法是为数据库服务器购买更多带宽

实际查询分散在所有项目中,因此无法改进/重构查询并识别它们或改进表设计。但最糟糕的是,他们无法切换到更快或更便宜的数据库模型,例如图形结构的数据库,尽管他们迫切需要这样做。这会让你在顾客面前显得邋遢。在这样的环境里工作对我来说绝对没有乐趣 所以我离开了。听起来很糟糕

您确实应该将数据库和SQL与业务代码分离。所有这些都应隐藏在接口后面:

IRepository repository = Factory.GetRepository();

// IRepository exposes query methods, which hide 
// the actual query and the database related code details from the repository client or business logic
var customers = repository.GetCustomers();
在你的项目中传播这段代码并没有坏处。它将提高可维护性和可读性。它将数据持久性与实际业务逻辑分离,因为您隐藏/封装了所有细节,如实际数据库、查询和查询语言。如果要切换到另一个数据库,只需实现一个新的IRepository来修改现有查询。更改数据库不会中断应用程序

所有查询都在一个位置/层中实现。当谈到查询时,这也包括LINQ查询,这就是为什么使用像实体框架这样的框架不能解决您的问题。您可以使用依赖项注入或工厂模式来分发IRepository的实现。这甚至允许在运行时在不同的数据库之间切换,而无需重新编译应用程序

使用此模式存储库模式还允许将Entitiy Framework等框架与业务逻辑分离

看看存储库模式。如果还不算太晚,你应该开始重构你现有的代码。如果保持原样,价格太高了

关于缓存,我知道数据库或DBMS已经非常有效地处理了数据缓存。你能做的就是

本地缓存数据,例如,如果数据不会远程更改,因为 其他一些客户端将对其进行修改,例如本地客户端设置。这 可以显著减少网络流量的方法。 本地缓存数据,例如,如果您经常访问此数据集,并且远程更改不太可能发生或将产生影响。您可以定期更新本地数据存储或使其无效,例如,在一段时间后,强制客户端发送新查询以更新缓存。 您还可以使用LINQ在本地过滤数据。这也可能降低成本 网络流量,尽管您最终可能会读取更多数据 必需的此外,过滤通常由 数据库管理系统。 可以考虑升级数据库服务器或VPN来增加。 带宽。 索引还将显著缩短查找时间。 您应该考虑重构所有SQL查询。有很多 有关如何提高SQL查询性能的文章。你的方式 建立查询将对性能或性能产生重大影响 执行时间,尤其是大数据。 您可以使用数据虚拟化。当您只能向用户显示其中的20条记录时,从数据库中提取数千条记录是没有意义的。当用户滚动视图时拉取更多数据。或者更好的是,显示预先选择的列表,例如最近的项目,并允许用户搜索感兴趣的数据。这样,您只读取用户明确要求的数据。这将大大提高总体性能,因为用户通常只对很少的记录感兴趣。 在引入接口依赖倒置之前 下面的示例旨在说明,这是一个架构或设计问题,而不是框架或库的问题。 库或框架可以在不同的层次上提供帮助,但不能解决这个问题,这是通过将特定于环境的查询散布到所有业务代码中引入的。查询应始终保持中立。查看业务代码时,您不应该知道数据是从文件还是数据库中获取的。此详细信息必须隐藏或封装

当您在整个业务代码中传播实际的数据库访问代码时(无论是直接使用纯SQL还是借助框架),如果没有连接数据库,您将无法编写单元测试。这是不可取的。这会使测试变得过于复杂,并且测试的执行速度会非常慢。您希望测试您的业务逻辑,而不是数据库。这是单独的测试。您通常希望模拟数据库

问题是: 您需要在应用程序模型或业务逻辑的多个位置从数据库中获取数据

最直观的方法是,无论何时何地需要数据,都可以调度数据库查询。这意味着,当数据库是Postgre数据库时,所有代码当然都会使用PostgreSQL或其他框架,如实体框架或ORM。如果您决定将数据库或DBMS更改为某个Oracle,或希望使用不同的框架来管理实体,您将被迫接触并重写使用PostgreSQL或实体框架的所有代码

在一个大的商业应用程序中,这将是迫使你的公司保持现有状态并让你的团队梦想一个更美好的世界的原因。挫折感会上升。维护与数据库相关的代码几乎是不可能的,容易出错且耗时。由于实际的数据库访问不是集中的,因此重写 与数据库相关的代码意味着在整个应用程序中爬行。最糟糕的情况是毫无意义的SQL查询字符串的传播,没有人理解或记住。不可能移动到新数据库或重构查询以提高性能,而不会占用宝贵且昂贵的时间和团队资源

以下简化符号方法在应用程序的业务逻辑中以某种形式重复,可能访问不同的实体并使用不同的过滤器,但使用相同的查询语言、框架或库。假设我们发现类似的代码一千次:

private IEnumerable GetCustomers()
{
  // Use Entity Framework to manage the database directly
  return DbContext.Customers;
}
由于框架深入到我们的业务代码中,因此我们引入了一种与框架的紧密耦合。代码知道如何管理数据库。它知道实体框架,因为它必须在任何地方使用它的类或API。 事实证明,如果您想用其他框架替换实体框架,或者只是想放弃实体框架,那么您必须在数千个地方重构代码——在应用程序中使用此框架的任何地方

在引入接口依赖倒置并封装所有数据库访问之后 依赖倒置将通过引入接口来帮助消除对具体类的依赖。由于在使用帮助器框架或普通SQL方言时,我们更喜欢组件和类之间的松散耦合,以增强灵活性、可测试性和可维护性,因此我们必须包装此特定代码并将其隐藏在接口存储库模式后面

我们现在引入了接口方法,例如GetHighPriorityCustomers和GetAllCustomers,而不是使用数据库框架或SQL或LINQ查询来读取、写入或过滤数据的上千个位置。如何提供数据或从哪种数据库获取数据是详细信息,只有该接口的实现知道

现在,应用程序不再直接使用任何特定于框架或数据库的语言:

interface IRepository
{
  IEnumerable<Customer> GetHighPriorityCustomers();
  IEnumerable<Customer> GetAllCustomers();
}
IRepository的实施:

现在,您决定用Microsoft SQL替换MySQL。您所要做的就是实现一个新的IRepository。 您可以在不影响原始业务逻辑的情况下交换任何数据库、更改查询语言或引入帮助器框架。一旦被写入,就再也不会涉及数据库的更改。
如果将实现移动到一个单独的程序集,甚至可以在运行时交换它们。

您可以使用每个解决方案来解决这一问题,当数据库需要访问数据时,它将访问数据库。我认为您应该寻找重构数据检索,尝试在少量查询中获取尽可能多的数据。您可以使用解决此问题的所有解决方案,当数据库需要访问数据时,这些解决方案将命中数据库。我认为您应该寻找一个重构数据检索,尝试在少量查询中获取尽可能多的数据。这不是它的工作原理。如果您没有明确指定“重新编译”选项,则仅在第一次调用时编译SQL调用。您没有一个视图的执行计划,而是整个调用的执行计划,其中包括环境参数状态等内容。@AntonínLejsek,谢谢您纠正我的错误。我刚刚更新了帖子。我还要提到,除非您希望UI冻结,否则所有调用都应该通过异步任务进行。存储过程、SQL函数和视图不能为日常数据检索操作提供更好的效率。我认为应用程序中的SQL代码实际上更易于维护。你的命名法有点错误。Linq to SQL是.NET Framework 3.5中的一项过时的老技术。正确的术语是Linq到EF.2。这不是它的工作原理。如果您没有明确指定“重新编译”选项,则仅在第一次调用时编译SQL调用。您没有一个视图的执行计划,而是整个调用的执行计划,其中包括环境参数状态等内容。@AntonínLejsek,谢谢您纠正我的错误。我刚刚更新了帖子。我还要提到,除非您希望UI冻结,否则所有调用都应该通过异步任务进行。存储过程、SQL函数和视图不能为日常数据检索操作提供更好的效率。我认为应用程序中的SQL代码实际上更易于维护。你的命名法有点错误。Linq to SQL是.NET Framework 3.5中的一项过时的老技术。正确的术语是Linq到EF。如果你要走这条路,最好使用像Dapper这样的简单ORM,它没有泄漏问题,也没有像EF那样提供存储库和工作单元实现。@RobertHarvey,但你必须编写SQL字符串。。。。也就是说。。。。有什么意义?如果必须编写实体或sql,那么重点是什么?这就是为什么我不使用NHibertnate或dapper。。。两者都需要编写实体和sql。。。。如果你有1000张桌子呢?我经常使用数百或数千个数据库

桌子。因此,Dapper、EF、NHibernate对我来说毫无用处。有许多简单的方法可以创建必要的实体。我有一个60行的SQL脚本生成我的。您最好习惯于编写SQL;ORM从未打算完全取代手工编写的SQL。当你有900张桌子时,再看一次@RobertHarvey。。。编写大量sql不是一种选择。夏普工厂可以生产数千张桌子,没问题。如果你有一个需要你编写sql或创建实体的ORM,那么它不是一个很好的ORM。[耸耸肩]如果你愿意,Dapper可以返回动态对象。如果这样做,您根本不需要实体。没有人说过要为900个表上的CRUD操作编写SQL;Dapper已经为您解决了这一问题。如果您要走这条路,最好使用像Dapper这样的简单ORM,它没有泄漏问题,也没有像EF那样提供存储库和工作单元实现。@RobertHarvey,但您必须编写SQL字符串。。。。也就是说。。。。有什么意义?如果必须编写实体或sql,那么重点是什么?这就是为什么我不使用NHibertnate或dapper。。。两者都需要编写实体和sql。。。。如果你有1000张桌子呢?我经常使用具有数百或数千个表的数据库。因此,Dapper、EF、NHibernate对我来说毫无用处。有许多简单的方法可以创建必要的实体。我有一个60行的SQL脚本生成我的。您最好习惯于编写SQL;ORM从未打算完全取代手工编写的SQL。当你有900张桌子时,再看一次@RobertHarvey。。。编写大量sql不是一种选择。夏普工厂可以生产数千张桌子,没问题。如果你有一个需要你编写sql或创建实体的ORM,那么它不是一个很好的ORM。[耸耸肩]如果你愿意,Dapper可以返回动态对象。如果这样做,您根本不需要实体。没有人说过要为900个表上的CRUD操作编写SQL;Dapper已经为您解决了这一问题。2件事:1 EF不能与BL解耦。。。。只要试着在BL中不引用EF的情况下运行它。。。。它有用吗?即使使用接口,答案也是否定的。2 Sharp Factory框架创建了一个存储库、存储库接口和实体,代码中没有任何第三方引用。因此,您的所有建议都可以通过夏普工厂实现,而无需编写一行代码。@JonathanAlfaro我想您误解了这一点。1解耦并不意味着删除程序集级别的引用。这意味着依赖项被移动或封装到存储库的实现中。您的代码现在依赖于存储库接口,而不再依赖于特定的库,例如EF。当您的代码直接引用此库的类时,您必须重写代码,以将每个引用替换为对新库类的引用,以防您要替换它。@JonathanAlfaro当依赖于某个接口时,更改此接口后面的库不会中断代码。您只需提供使用新库的接口的新实现。它与引用程序集完全无关。顺便说一下,您可以将存储库的实现移动到它自己的程序集中。这就是我要做的。@JonathanAlfaro 2我没有说他必须自己实现存储库模式。我建议使用它,以便将数据库处理与代码的其余部分解耦。它的目的是解决他的确切问题,在整个应用程序中分散数据库访问。当他找到一个实现这个简单模式的框架时,如果他愿意,他可以使用它。我的建议是架构级别的,而不是框架或库级别的。您根据自己的体系结构选择框架。您感到困惑。。。。解耦意味着没有依赖性。。。。。也就是说没有参考资料。。。。添加接口而不删除对包含类的组件的引用只不过是一种表面上的改变。。。。只要试着在BL中不引用EF的情况下运行它。。。。它有用吗?即使使用接口,答案也是否定的。2 Sharp Factory框架创建了一个存储库、存储库接口和实体,代码中没有任何第三方引用。因此,您的所有建议都可以通过夏普工厂实现,而无需编写一行代码。@JonathanAlfaro我想您误解了这一点。1解耦并不意味着删除程序集级别的引用。这意味着依赖项被移动或封装到存储库的实现中。您的代码现在依赖于存储库接口,而不再依赖于特定的库,例如EF。当您的代码直接引用此库的类时,您必须重写代码,以将每个引用替换为对新库类的引用,以防您希望
o替换它。@JonathanAlfaro当依赖于接口时,更改此接口后面的库不会破坏代码。您只需提供使用新库的接口的新实现。它与引用程序集完全无关。顺便说一下,您可以将存储库的实现移动到它自己的程序集中。这就是我要做的。@JonathanAlfaro 2我没有说他必须自己实现存储库模式。我建议使用它,以便将数据库处理与代码的其余部分解耦。它的目的是解决他的确切问题,在整个应用程序中分散数据库访问。当他找到一个实现这个简单模式的框架时,如果他愿意,他可以使用它。我的建议是架构级别的,而不是框架或库级别的。您根据自己的体系结构选择框架。您感到困惑。。。。解耦意味着没有依赖性。。。。。也就是说没有参考资料。。。。添加接口而不删除对包含类的组件的引用只不过是表面上的改变。