在我工作的项目中,我有查询/更新数据库的类,比如这个,
public class CompanyInfoManager
{
public List<string> GetCompanyNames()
{
//Query database and return list of company names
}
}
随着我不断创建越来越多的这类课程,我意识到我可能应该创建这种类 static 。通过这样做,显而易见的好处是避免每次需要查询数据库时都需要创建类实例。但是因为对于静态类,只有一个类的副本,这会导致数百个请求只竞争一个静态类的副本吗?
谢谢,
答案 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;
所以现在你不会为单元测试牺牲任何灵活性,因为所有类的依赖都是通过它的构造函数传递给它的