我应该让这个类静态吗?

时间:2010-07-14 21:19:45

标签: c#

在我工作的项目中,我有查询/更新数据库的类,比如这个,

public class CompanyInfoManager
{
    public List<string> GetCompanyNames()
    {
         //Query database and return list of company names
    }
}

随着我不断创建越来越多的这类课程,我意识到我可能应该创建这种类 static 。通过这样做,显而易见的好处是避免每次需要查询数据库时都需要创建类实例。但是因为对于静态类,只有一个类的副本,这会导致数百个请求只竞争一个静态类的副本吗?

谢谢,

5 个答案:

答案 0 :(得分:12)

我不会将该类设为静态,而是使用依赖注入并将所需资源传递给该类。这样您就可以创建一个模拟存储库(实现IRepository接口)来进行测试。如果你使类静态并且没有传入你的存储库那么就很难测试,因为你无法控制静态类连接的内容。

注意:下面的代码是一个粗略的例子,仅用于表达这一点,不一定是编译和执行。

public interface IRepository
{
   public DataSet ExecuteQuery(string aQuery);
   //Other methods to interact with the DB (such as update or insert) are defined here.
}

public class CompanyInfoManager
{
   private IRepository theRepository;
   public CompanyInfoManager(IRepository aRepository)
   {
      //A repository is required so that we always know what
      //we are talking to.
      theRepository = aRepository;
   }

   public List<string> GetCompanyNames()
   {
      //Query database and return list of company names
      string query = "SELECT * FROM COMPANIES";
      DataSet results = theRepository.ExecuteQuery(query);
      //Process the results...
      return listOfNames;
   }
}

测试CompanyInfoManager:

//Class to test CompanyInfoManager
public class MockRepository : IRepository
{
   //This method will always return a known value.
   public DataSet ExecuteQuery(string aQuery)
   {
      DataSet returnResults = new DataSet();
      //Fill the data set with known values...
      return returnResults;
   }
}

//This will always contain known values that you can test.
IList<string> names = new CompanyInfoManager(new MockRepository()).GetCompanyNames();

我不想在依赖注入方面徘徊。 Misko Hevery's blog详细介绍了great post to get started

答案 1 :(得分:2)

这取决于。你需要让你的程序多线程吗?您是否需要连接到多个数据库?你是否需要在这堂课中存储州?您需要控制连接的生命周期吗?您将来需要数据缓存吗?如果您对其中任何一个回答“是”,则静态类会使事情变得尴尬。

我个人的建议是将它作为一个实例,因为这更像是OO,并且会为您提供将来可能需要的灵活性。

答案 2 :(得分:1)

你必须小心使这个类静态化。在Web应用程序中,每个请求都在其自己的线程上处理。如果不小心,静态实用程序可能是线程不安全的。如果发生这种情况,你就不会幸福。

我强烈建议您遵循DAO模式。使用像Spring这样的工具让你轻松上手。您所要做的就是配置数据源,您的数据库访问和事务将变得轻而易举。

答案 3 :(得分:0)

如果你去静态课程,你必须设计它,使其基本上无国籍。通常的策略是创建一个具有公共数据访问功能的基类,然后在特定的类中派生它们,比如加载客户。

如果对象创建实际上是整个操作的开销,那么您还可以查看池化预先创建的对象。但是,我非常怀疑情况就是这样。

您可能会发现许多常见的数据访问代码都可以构建为静态方法,但是所有数据访问的静态类似乎都在某处丢失了设计。

静态类本身对多线程访问没有任何问题,但显然锁定和静态或共享状态存在问题。

答案 4 :(得分:0)

通过使类静态,你将有一个艰难的单位测试它,就像你 可能必须以非清晰的方式在内部管理连接字符串的读取,方法是从配置文件中读取类内部,或者从管理这些常量的某个类中请求它。我宁愿以传统方式实例化这样一个类

var manager = new CompanyInfoManager(string connectionString /*...and possible other dependencies too*/)

然后将其分配给全局/公共静态变量,如果这对于类有意义,即

//this can be accessed globally
public static CompanyInfoManager = manager;

所以现在你不会为单元测试牺牲任何灵活性,因为所有类的依赖都是通过它的构造函数传递给它的

相关问题