【问题标题】:Use a static class differently depending on context it was called根据调用的上下文不同地使用静态类
【发布时间】:2015-11-16 16:08:47
【问题描述】:

我有一个静态类,它的唯一工作是通用 SQL 调用的包装器。但是,根据调用静态类的类,我想相应地设置 connectionString(它是包装类中的公共静态字符串)。如果可能的话,我希望它根据使用的上下文推断要使用的连接字符串,而不必传递它。

有没有办法按照我的要求去做?

以这种方式使用静态类是不好的做法吗?

我不太关心有一个只包装 sql 调用的非静态类,维护该对象似乎是额外的工作。

包装器:

public static class SqlServer
{
    private static readonly string SqlConnectionString = ConfigurationManager.ConnectionStrings["foo"].ConnectionString;

    /// <summary>
    ///     Single point of entry for SQL queries that need to return a LIST of well-defined objects
    /// </summary>
    public static IEnumerable<T> ExecuteQuery<T>(SqlConnection sqlConnection, string sql, object param, int? timeout = null)
    {
        if (sqlConnection != null)
        {
            return sqlConnection.Query<T>(sql, param, commandTimeout: timeout).ToList();
        }

        using (var tempSqlConnection = new SqlConnection(SqlConnectionString))
        {
            tempSqlConnection.Open();
            return tempSqlConnection.Query<T>(sql, param, commandTimeout: timeout).ToList();
        }
    }
}

应该使用“bar”连接字符串:

public class BarController : ApiController
{
    [HttpGet]
    public int getUserId(string username)
    {
        var args = new
        {
            USERNAME = username
        };

        const string sql = @"SELECT id FROM users WHERE username = @USERNAME";

        return  SqlServer.ExecuteQuery<int>(null, sql, args).Single();
    }
}

应该使用“foo”连接字符串:

public class FooController : ApiController
{
    [HttpGet]
    public int getUserId(string username)
    {
        var args = new
        {
            USERNAME = username
        };

        const string sql = @"SELECT id FROM users WHERE username = @USERNAME";

        return  SqlServer.ExecuteQuery<int>(null, sql, args).Single();
    }
}

【问题讨论】:

  • 显示现有代码。
  • 您需要提供有关您正在尝试做什么的更多信息,并显示您关注的代码的特定部分。显然,如果您希望它使用不同的连接字符串,您可以传递一个参数,那么问题是什么?你也可以使用继承——我不知道为什么你的类需要是静态的。
  • “必须维护该对象似乎是额外的工作” - 如果您在很多地方都需要它,那么 那个 就是您的问题。
  • 拥有一个带有静态连接字符串的静态类并更改此静态连接字符串会导致并发问题,最终会在错误的数据库上执行错误的查询。我希望你不是要根据调用者来改变比方说 ExecuteReader 方法中的静态连接字符串
  • 您可能正在寻找的是Repository pattern

标签: c#


【解决方案1】:

有没有办法做我所要求的? 以这种方式使用静态类是不好的做法吗?

总有办法,但有些事情不应该做,除非你了解后果。这是不应该做的事情之一。强制静态类表现得像一个可变对象几乎没有充分的理由。所以,是的,这是不好的做法。

静态类包装的 SQL 方法需要连接。该类可以使用从调用者传入的参数提供与这些 SQL 方法的连接,这就是您现在正在做的事情(一种可接受的做法)。或者该类可以包含提供连接本身,这意味着它将把它存储为一个属性,并在调用 SQL 方法时使用它。

使用静态类意味着您希望连接字符串在初始化后保持不变;除非您公开一个方法(公共属性)来更改它,否则它不会在进程的生命周期内更改,这会使您容易受到并发问题的影响。通过根据调用者进行更改,您将使其成为非常量。

您要做的是让静态类从调用者那里提取连接的值。这违反了OOP的封装原则。

更好的做法是做您认为“额外工作”的事情。让每个调用者实例化这个包装类的一个对象,在构造函数参数中提供连接字符串。

【讨论】:

  • 这并没有我想象的那么多工作,我只是最终让对象成为 apicontroller 的静态成员。私有静态只读 SqlServer SqlServerObj = new SqlServer(ConfigurationManager.ConnectionStrings["bar"].ConnectionString);所以这行得通。谢谢
  • 有趣。我一般避免使用静态成员;它们往往会导致并发问题。在你的情况下,它可能工作得很好,但不要过于依赖这种模式,否则会给你带来麻烦。
【解决方案2】:

您可以将对象传递给您正在调用的静态方法,然后打开该对象的类型以设置连接字符串。

例如

public static ConnectToDb(object _Object)
{
    switch(typeof(_Object))
    {
       //Set connection string...
    }
    // Do some stuff
}    

通过 ConnectToDb(this)... 或其他方式调用

【讨论】:

  • 你不能这样做,因为你试图使用一个像类型这样的变量。您的方法也需要返回类型。
  • @JamieR,此外,您不能在 Type 的实例上使用 switch
  • 你当然是正确的 - 我试图显示 sudo 代码并且语法略有错误,但你可以打开类似 _Object.GetType().ToString() 的东西。有了问题中的额外细节,我不确定这种方法是否真的会有很大帮助,但它是可行的......
  • 如果您打算将 anything 传递给静态方法,为什么要传递对象?为什么不直接传递连接字符串?但是如果你真的想要做这样的事情,那么你应该把它抽象出来,而不是object:传入一个实现你的自定义接口的对象,比如ISqlCaller,它有一个@ 987654326@财产什么的。 public static ConnectToDb(ISqlCaller caller)...
  • 我不建议按照我刚才所说的去做,顺便说一句。我支持我的回答,而不是这个评论。
猜你喜欢
  • 2023-03-15
  • 2020-11-04
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 1970-01-01
  • 2012-11-02
  • 2018-05-13
相关资源
最近更新 更多