【问题标题】:What are the possible issues of using single static instance of the de EnterpriseLibrary Database class for a DataLayer library?对 DataLayer 库使用 de EnterpriseLibrary Database 类的单个静态实例可能会出现哪些问题?
【发布时间】:2014-02-27 02:00:49
【问题描述】:

我正在重构许多项目,我想将访问数据库的所有方法组合到一个 DataLayer 库中(而不是每个项目都有自己的访问数据库的类)

这是我现在正在做的方法

private static Database DB = null ;
private static EventLog LOG = null ;

public static void Initialize()
{
    string logName;

    if (LOG == null)
    {
        logName = "DataLayer";

        LOG = new EventLog();

        if (!EventLog.Exists(logName))
        {
            //can fail because lack of permissions or other errors
            try
            {
                EventLog.CreateEventSource(logName, logName);
            }
            catch (Exception)
            {

            }
        }

        LOG.Source = logName;
    }
    if (DB == null)
    {
        DB = DatabaseFactory.CreateDatabase("Name");
    }

}

public static DataSet GetInfoFromDB(String param1, bool automatic)
{
    DataSet resp;
    DbCommand dbCommand;
    object[] pars;

    resp = null;
    dbCommand = null ;

    try
    {
        //prepare the parameters
        pars = new object[2];
        pars[0] = param1;
        pars[1] = automatic;

        dbCommand = DB.GetStoredProcCommand("StoredProcedureName", pars);
        dbCommand.CommandTimeout = 1200;

        resp = DB.ExecuteDataSet(dbCommand);
    }
    catch (Exception ex)
    {
        LOG.WriteEntry(string.Format("Error al ejecutar el StoredProcedure \"GetInfoFromDB\" {0}", ex.Message), EventLogEntryType.Error, 2004);
    }
    finally
    {
        if (dbCommand!= null)
        {
            dbCommand.Dispose();
        }
    }

    return resp;
}

对 DataLayer 库使用 de EnterpriseLibrary Database 类的单个静态实例可能会出现哪些问题?

我所说的问题是指连接泄漏,或者当多个进程开始调用这些方法或任何其他方法时,一个方法会以某种方式影响其他方法

我通常会通过试错来解决这个问题,但我想根据概念和技术/官方信息得到答案

添加

DataLayer 的主要目标和我计划的重构是采用所有 DB 实用程序/常用方法,如 GetAllParameters 以及在每个项目中反复复制的许多其他方法,以避免在每个项目中维护和测试它们。

我想要的是一个独特的方法 GetAllParameters 在所有其他项目中被调用/重用

因此,所有可以被许多项目使用且不属于特定业务逻辑的 Common 方法将被放置在 DataLayer.Common 中,如 DataLayer.Common.GetAllParameters

每个特定于特定功能的逻辑都将进入其自己的DataLayer.BusinessLogicA.GetSpecificInfo

值得一提的是,此 DataLayer 将用于此类项目

Website-->WebService-->BusinessLogic-->Datalayer
Winservice-->Datalayer
Winform-->Datalayer

【问题讨论】:

标签: c# enterprise-library enterprise-library-5


【解决方案1】:

对于你的所有项目,我假设所有项目都在同一个解决方案中,除非你是 DB/.Net 专家,否则在同一个地方混合来自不同解决方案的数据库访问是很疯狂的。

1) 您失去了对数据库的并行访问权限,具体取决于您的项目,这可能不是问题,如果是 Web 项目,请不要这样做,因为对服务器的所有调用都会阻塞。

2) 使用建议的方法,您将在每个项目和数据访问中混合业务逻辑,这很糟糕,难以维护,尝试查看 Entity Framework 和其他库来自动访问数据库

3) 使用 Enterprise Library 中的 Unity 将 DB 上下文注入到每个项目中,这将使其更具可测试性,我不会详细说明,因为 WEB 上有数百个示例,但它可能是解决方案为什么要进行重构。

总而言之,这样做可能是一个错误的决定,这完全取决于你为什么这样做。

[编辑]

您想要的是像 System.Linq 库这样的扩展方法来执行此操作,您需要创建一个静态类来实现第一个参数等于 this Database DB 的静态方法

public static MyClass
{
    public static DataSet GetAllParameters(this DataBase DB, int someParam, ...)
    {
        <your DB function to get them>
    }
}

然后你使用它你只需添加一个using MyClass 并在任何数据库对象中做var dataSet = DB.GetAllParameters(someParam, ...)

这会影响性能,如果你传递了错误的数据库,它会炸毁,但这是一种快速的方法,我强烈建议你使用自动 DAL 生成器查看 IOC 选项,这会将数据库对象更改为一些特定的表对象,并且在编译时进行了许多此解决方案不做的验证。

【讨论】:

  • 2) 我不想混合它们我想为像 GetAllParameters 这样在每个项目上一遍又一遍地实现的方法保留一个实现
  • 1) 我的一些项目是网站化的,它们使用访问数据库的 Web 服务。所有其他项目都是 Winforms 或 Winservices
  • Pedro The Kid 我在原始问题中添加了更多详细信息,如果需要,请您更新您的答案
  • @MauricioGracia 相应地更改了回复。
  • IoC = 此处提到的控制反转dotnetslackers.com/articles/designpatterns/…,您对以下问题stackoverflow.com/questions/7493319/…的答案有何看法
【解决方案2】:

可以将您的记录器作为静态类,但不能用于连接到数据库。

建议您使用 using 语句而不是静态函数,以便在使用后自动释放。

看到这个:Is the database connection in this class "reusable"?

这种做法避免了内存泄漏,

【讨论】:

  • Sr PEDRO 我看不出 USING 和 STATIC "FUNCTION" 在处理方面的关系。据我所知, USING 可以用于静态方法。我使用 try catch 是因为我想用 catch 记录问题的原因。如果你能告诉我如何在不嵌套另一个尝试的情况下将 USING 与 CATCH 一起使用,请告诉我
  • 对不起,我搞混了,我以为你在哪里使用 sqlConnection 或 EF,所以我不是在谈论将放置在静态方法中的东西,我指的是你处理 dbCommand 但不是SqlConnection 或 DbContext。但再读一点,我发现 Database 类自动管理连接的打开、关闭和池。
  • 如果您使用 EF,那么您可以考虑存储库模式,它允许您进行单元测试并注入 DbContext,并且您拥有所需的抽象层。 remondo.net/repository-pattern-example-csharp
  • SrPedro 我使用的是 ENTERPRISE LIBRARY 而不是 ENTITY FRAMEWORK 我把它们混在一起了
【解决方案3】:

任何时候你让一个类成为静态的,你都会让它更难测试。具体来说,您不能通过像Moq 这样的框架运行它。仅这一点就足以使其实例化。

正如 Pedro.The.Kid 在他的回答中所说,使用 UnityContainer 注入(这意味着您的数据访问对象要实现一个接口)将大大有助于使其成为一个管理良好的对象。

【讨论】:

    【解决方案4】:

    我建议使用 IOC 容器并让容器来处理您的 DataClass 的生命周期,您可以使用任何您想要的容器,如果您想遵循 microsoft 库然后使用 Unity,它是企业库的一部分。

    您可以尝试使用单例或瞬态测试它们,看看您更喜欢什么。

    你可以在你的复合根中使用这样的东西:

     public static void Register(IUnityContainer container)
    {
        container
            .RegisterType<Database>(
            new ContainerControlledLifetimeManager(),
            new InjectionFactory(c => DatabaseFactory.CreateDatabase("Name")));
    }
    

    查看this answer 以获得更详细的说明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-12
      • 2013-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多