【问题标题】:Is it possible to require a connection string in the DbContext constructor, configured from DI (startup.cs) without IDbContextFactory?是否可以在没有 IDbContextFactory 的情况下从 DI (startup.cs) 配置 DbContext 构造函数中的连接字符串?
【发布时间】:2017-05-21 19:51:08
【问题描述】:

抱歉,如果这令人困惑,我的脑袋正在试图找到解决方案,所以我的解释可能很糟糕。只是将我指向正确的方向将是有益的,我会根据需要进行澄清。这很可能只是我对 DI 缺乏了解。提前致谢!

我在两个应用程序之间共享的独立库中有一个 DBContext (EF6)……一个 ASP.Net Core 1.x 网站和一个 Azure Web 函数(使用 azure 函数核心工具)。当然,这些使用不同的设置文件,但这完全是另一个问题。我不想使用任何“硬编码”的连接字符串,所以我尝试设置 DI 以使用 appsettings.json 连接字符串:

var connectionString = connectionStrings.Data.App1.ConnectionString;
services.AddScoped<AppDbContext>(_ => new AppDbContext(connectionString));

我还使用了一个已设置为的通用存储库:

services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

存储库与 DBSet 中的特定实体一起使用。然后为每个资源使用一个服务。每个服务的实现(可以在 MVC 页面中使用或从 API 端点使用)访问存储库。例如,Configuration 服务的构造函数是 ..

public AppConfigurationService(IRepository<AppConfiguration> repo)

注册为

services.AddScoped<IService<AppConfiguration>, AppConfigurationService>();

存储库的构造函数接受我认为会使用上面的连接字符串的“AppDbContext”实例。

public Repository(AppDbContext context)

在调试时,我注意到连接字符串并不总是设置。当 AppConfigureServices 执行时...连接字符串按预期传入。但是当控制器实例化一个服务时,连接字符串总是空的,所以会调用默认的 DBContext 构造函数。

我家控制器的构造函数设置为

public HomeController(IService<AppConfiguration> service)

当我尝试从控制器的任何操作访问服务的 Repo 时,会在没有连接字符串的情况下更新 DbContext。

是否可以在 startup.cs 中以这种方式设置连接字符串?我对通用基类的使用会弄乱 DI 吗?如果我使用 IDbContextFactory,有什么方法可以在转到配置文件之前确定是否有可用于 DbContext 的连接字符串?

再次感谢您的任何建议/指导。

更新

考虑一下,AppConfigurationService 继承自 BaseService,定义如下:

public class AppConfigurationService : BaseService<AppConfiguration>
...
public abstract class BaseService<TEntity>: IService<TEntity> where TEntity : class, IEntityId<Guid>

不从 BaseService 继承的服务,例如:

public class ConnectionService: IService<Connection>, IServiceClone<Connection>

使用连接字符串更新。因此,只有继承自 BaseService 的服务没有与 DBContext 的连接字符串。

【问题讨论】:

    标签: .net dependency-injection asp.net-core entity-framework-6 azure-functions


    【解决方案1】:

    也许您可以尝试将连接字符串设置为单例,因为您有两个独立的应用程序共享同一个存储库。

    类似这样的:

    interface IConnectionProvider { string GetConnectionString(); }
    public class ConnectionProvider : IConnectionProvider { public string GetConnectionString() { return connectionStrings.Data.App1.ConnectionString; } }
    
    services.AddSingleton<IConnectionProvider, ConnectionProvider>();
    

    然后修改你的 DbContext 以接收连接提供者:

    public AppDbContext(IConnectionProvider provider) : base(provider.GetConnectionString())
    

    希望对你有帮助。

    【讨论】:

    • 非常感谢!我将尝试使用 IOptions 并让您知道结果。
    • 使用 IOptions 并没有真正的改变,一些调用仍然没有连接字符串,而大多数调用都有。失败代码和工作代码的堆栈跟踪具有相同的来源。如果我发现其他任何事情,我会告诉你。感谢您抽出宝贵时间。
    • 你如何在控制器上实例化你的服务,字符串连接为空?你是通过 DI 还是硬编码方式获得的?
    • 因此,控制器中的连接字符串并不是空的,而是始终传入的。某些东西(内部,不是我正在拨打的电话,因此尝试调试它的问题)正在实例化。大多数时候我的“AppDbContext(string connectionString) base(connectionString)”被调用。在极少数情况下,会实例化默认的“AppDbContext()”构造函数。我不能总是让它发生,一旦在控制器中发生这种情况,所有后续调用都会设置连接字符串。虽然这个控制器是“public HomeController(IService service)”
    • 该服务被实例化为 ... "public ConfigurationService(IRepository repo) : base(repo, AppTier.Application) {}" ... 看起来像 ..."public Repository (AppDbContext 上下文,IMapper 映射器) : base(context, mapper) { }"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 2010-10-10
    • 2012-04-24
    相关资源
    最近更新 更多