在我的ASP.NET MVC应用程序中,我有一个包含所有业务逻辑/服务层的项目。该项目与我的数据库(实体框架)进行交互,该数据库位于一个单独的项目中。
我希望能够轻松访问服务层,因此我在其中创建了静态类,以便轻松引用它们。例如,如果我在我的控制器中,我需要创建一个新帐户:
ServiceLayer.Accounts.CreateAccount(userName, passWord) //etc..
然后服务层执行所有必需的逻辑,然后通过DatabaseLayer
中的存储库创建用户。
private static AllRepos _Repos;
private static AllRepos Repos {
get
{
if(_Repos == null)
_Repos = new AllRepos();
return _Repos
}
}
public static void CreateAccount(string username, password)
{
string salt = GenerateSalt();
Account newAccount = DatabaseLayer.Models.Account
{
Name = username,
Password = HashPassword(password, salt),
Salt = salt
};
Repos.AddAccount(newAccount);
}
因为我不想在我的服务层中到处执行以下操作:
AccountRepository Accounts = new DatabaseLayer.AccountRepository();
我为我的存储库创建了一个包装类,这样我只需要实例化一次就可以使用所有其他存储库。
public class AllRepos
{
private AccountRepository _Accounts;
public AccountRepository Accounts
{
get
{
if (_Accounts== null)
_Accounts= new AccountRepository();
return _Accounts;
}
}
// the same is done for every other repository (currently have about 10+)
}
在服务层的静态类中使用了它。
因为我的所有服务层类都是静态的,Repos
字段也是静态的,所以我遇到的一个明显问题是从多个datacontexts中检索相同的对象,导致更新/删除的奇怪行为。
我理解,如果我使用静态成员/类,因为它们会持续应用程序的生命周期,这是可以预期的,但有没有办法可以将服务层用作ServiceLayer.Accounts.Method()
而不需要必须创建一个非静态类,需要在使用它的任何地方进行实例化,并且由于多个datacontext实例而不会遇到CRUD问题?
答案 0 :(得分:15)
你的方法确实不是推荐的方法。就个人而言,我永远不会允许我的团队使用这种方法。缺点:
创建存储库实例的最大原因是,如果需要,可以注入依赖项。对此最着名的论点是单元测试,因此您可以模拟依赖项,但我已经构建了许多存储库,这些存储库具有在生产代码中更改的接口依赖项。
您应该简单地将存储库实例化作为基本服务类的一部分。没有理由它必须是“静态 OR 实例调用”。基类中应该有有限的实例实例化代码。
答案 1 :(得分:10)
我不确定为什么你对使用实例这么死定。除了您现在拥有的代码不必要的复杂之外,使用静态类型也会使单元测试变得更加困难。静态类型就像一个你无法模拟/替换的单例。在我看来,你真正的问题可能是,“我如何终身管理我的服务层实例?”通常,您通过为每个Web请求设置一个实例来执行此操作。在ASP.NET MVC应用程序中,您可以new up a DI container via a ControllerFactory, and handle all of this. [PDF]
答案 2 :(得分:1)
您需要有意识地处理objectcontext的范围,例如执行Unit Of Work pattern
除此之外,我认为你应该重新考虑做一切静态的事情,因为womp说你得到了很高的耦合,并且很难测试,你可以通过使用一个来管理依赖图得到很多帮助。 IOC容器。
我可以这么说,以前烧过自己这样做的事情:)
答案 3 :(得分:-3)
单身人士(以及所描述的静态课程)是邪恶的,应该不惜一切代价避免,特别是在网络应用程序中。