【问题标题】:Connect to database using dependency injection使用依赖注入连接到数据库
【发布时间】:2017-12-04 23:12:41
【问题描述】:

我正在尝试学习如何使用依赖注入,但是在涉及到我的数据库时遇到了一些麻烦。到目前为止,这是我的过程:

我有一个 MVC 项目,其中控制器使用我的类库中的不同存储库。 所有存储库都使用相同的数据库。

一开始我使用SimpleInjector注册Repositories Application_start方法:

var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
var client = new GraphClient(uri, username, password);
container.Register<IRepoA>(() => new RepoA(client);
container.Register<IRepoB>(() => new RepoB(client);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();

DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

在每种方法中,我都这样做了:

  client.Connect();
  client.performSomeQuery();
  client.Dispose();

这可行,但这意味着我每次调用方法时都会重新连接到数据库。 为避免这种情况,将连接调用移至此处:

var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
var client = new GraphClient(uri, username, password);
client.Connect();
container.Register<IRepoA>(() => new RepoA(client);
container.Register<IRepoB>(() => new RepoB(client);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();

但是我从来没有处理掉我的连接。

我现在想的是注册我的数据库客户端;

container.RegisterSingleton(() =>
{
    var client = new GraphClient(uri, username, password);
    client.Connect();
    return client;
});

然后像这样注入它:

container.Register<IRepoA>(() => new RepoA(container.GetInstance<GraphClient>()));

这是正确的做法吗?

是否正确理解连接将在容器生命周期结束时被释放?

当我注册客户端时,我确实得到了一个“隐式捕获的闭包:容器”。

【问题讨论】:

  • 为每个请求创建一个新连接将是正常的方法。想一想——一个 Web 应用程序可能必须同时处理数十或数百个请求。你不希望这些东西都在争夺同一个实际的连接对象。
  • 我刚读过这篇文章,认为调用@GPW 很昂贵“对于每个要与之通信的数据库,您应该只拥有一个实例(通常是一个)这样可以避免过多的调用到需要往返 Neo4j 服务器的 Connect() 方法”link 在每个方法中调用 connect 是否足够(就像我首先做的那样)或者我应该在每个方法中使用 (var client = new GraphClient(_uri, _username, _password) ) { client.Connect();客户端.Query();客户端.Dispose(); }
  • 我明白了,我没有意识到您使用的是线程安全的特定库并建议使用单例方法。您使用 Lambda 注册课程有什么原因吗?我希望您只需要使用 DI 注册类及其实现 - 它实际上应该为您创建它们(因此您无需指定如何创建 IRepoA 并因此避免关闭警告)

标签: c# model-view-controller dependency-injection database-connection simple-injector


【解决方案1】:

做事的方法不止一种......所以有时要求正确的方法可能会让你走上错误的道路......

但这是我在你的情况下会做的......

我将引入一种称为工作单元的模式......将其视为业务交易

您打开一个工作单元并在其生命周期内执行各种数据库交互,可能都在一个数据库事务中。所有这些交互都可能分布在不同的存储库中。如果您的整批交互都没有出现需要回滚的错误,则声明工作单元完成并离开其范围(范围为 using(...) 范围)

如果出现错误,您没有在其生命周期结束之前声明它完成...

在工作单元的生命周期结束时,您可以提交或回滚所有底层数据库事务(通常只有一个),具体取决于是否声明了完成

这个工作单元对象通常还包含我的数据库连接对象并提供到存储库的连接

再次使用依赖注入,您可以使用工厂方法根据存储库在实例化期间请求的接口提供不同的数据库连接...

通常需要连接的第一个 repo 会导致工厂创建一个并打开它(可选地,您可以根据使用的 repos 有不同的连接),而要求连接的第二个 repo 会获得一个已创建的连接,并且之前打开...

工作单元的结束(参见 IDisposable)也意味着 connectionfactory 的结束...... connectionfactory 的结束意味着打开的连接和 repos 的结束......因为后者被实例化为 using 块,并且根据使用的资源,他们不应该离开所说的块

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-20
    • 2016-08-22
    • 2017-08-19
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多