首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将配置文件中的连接字符串注入EF核心DbContext

将配置文件中的连接字符串注入EF核心DbContext
EN

Stack Overflow用户
提问于 2019-03-29 05:25:28
回答 2查看 2.8K关注 0票数 0

我需要在我的项目的DbContext类中注入一个依赖项。我正在尝试以一种遵循“干净架构”的方式来做这件事。

我需要能够使用DbContext的空构造函数,同时仍然引用配置文件中的连接字符串。

我利用这个通用存储库并将其注入到服务中。它是在应用层中定义的。

代码语言:javascript
复制
     public class GenericRepository<C, T> : IGenericRepository<C, T> where T : class where C : DbContext, new()
     {
        private DbContext _entities = new C();
     }

在我的EF Core上下文类(在持久层中定义)中,我有:

代码语言:javascript
复制
   public partial class MyContext : DbContext
   {
       private IConnectionStringProvider _connectionStringProvider;  

        public virtual DbSet<MyEntity> { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {  
                optionsBuilder.UseSqlServer(_connectionStringProvider.GetConnectionString());
            }
        }
    }

我还在持久层中定义了IConnectionStringProvider的实现。如果需要的话,我希望这个实现可以很容易地交换。目前,它从App.config读取并使用ConfigurationManager nuget包。但这在未来可能会改变,因此它需要很容易地进行交换。

IConnectionStringProvider在应用层定义:

代码语言:javascript
复制
 public interface IConnectionStringProvider
 {
     string GetConnectionString();
 }

在我的表示层中,我有一个ASP.NET核心MVC项目。在StartUp.cs中,我使用标准的方式将dbContext注入到我的控制器中:

代码语言:javascript
复制
services.AddDbContext<ContractsWorkloadContext>();

如果我用下面的方法覆盖OnModelCreatingMethod,我可以让它正常工作。

代码语言:javascript
复制
 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
 {
     if (!optionsBuilder.IsConfigured)
     {
         _connectionStringProvider = new ConnectionStringProvider();
         optionsBuilder.UseSqlServer(ConnectionStringProvider.GetConnectionString());
     }
 }

此方法允许我将配置中的连接字符串值与空的上下文构造函数实例一起使用,这是它与我的通用存储库一起使用所必需的,并且仍然能够使用带有DbContextOptionsBuilder参数的构造函数。

我唯一要解决的问题是如何在上下文不依赖于实现的情况下实现这一点。

我尝试过Autofac属性注入,方法是注册IConnectionStringProvider接口和实现,以及使用属性“自动连接”注册Context类。但该属性始终为空。

是的,我知道上面是一个字段,而不是一个属性。我尝试修改context类,使其具有属性而不是字段。我甚至尝试创建一个方法来设置字段,并使用带有autofac的方法注入。但是属性/字段在任何情况下都是空的。

代码语言:javascript
复制
 builder.RegisterType<ConnectionStringProvider>().As<IConnectionStringProvider>()();
 builder.RegisterType<MyContext>().PropertiesAutowired();

代码语言:javascript
复制
 builder.RegisterType<ContractsWorkloadContext>().OnActivated(e =>
 {
     var provider = e.Context.Resolve<IConnectionStringProvider>();
     e.Instance.SetConnectionstringProvider(provider);
 });

总而言之,我需要:

  1. 将连接字符串注入上下文设计允许空的构造函数实例creation
  2. Maintain "Clean Architecture“

这里的任何帮助都将不胜感激。

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-23 23:49:20

这是一种更好的方式。对于那些偶然发现这一点的人..

更具体的存储库实现只是扩展基本存储库实现的类。例如:

代码语言:javascript
复制
EFCustomerRepository : EFRepository<MyContext, Customer>

现在,我可以通过依赖注入在整个应用程序中的任何位置注入IMyEFCoreDatabase,并引用存储在实现中的存储库。

这是比上面更好的方式,因为我的存储库不再调用new C()。相反,它们现在通过构造函数注入来注入上下文。

票数 0
EN

Stack Overflow用户

发布于 2019-03-29 08:46:58

我最终做的是创建一个对连接字符串的静态引用,然后在返回该值的上下文中创建一个readonly属性。

通过这种方式,我能够在应用层中抽象IConnectionStringProvider并在基础架构层中实现它。这将允许在需要时以最小的努力换出实现。

此外,通过添加返回静态连接字符串的readonly属性,我能够使用利用new()的通用存储库,并且仍然可以从配置文件中获取连接字符串。

这样做的唯一缺点是,连接字符串在整个应用程序生命周期内都存储在内存中。

静态值由提供程序实现在表示层的StartUp.cs文件中设置。

这绝对管用..。但如果有更好的办法我会洗耳恭听。:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55407069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档