0

我需要为我的项目注入一个依赖项到我的 DbContext 类中。我试图以遵循“清洁架构”的方式来做到这一点。

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

我利用这个 Generic Repository 并将其注入到服务中。它在应用层中定义。

     public class GenericRepository<C, T> : IGenericRepository<C, T> where T : class where C : DbContext, new()
     {
        private DbContext _entities = new C();
     }

在我的 EF Core Context 类(在持久层中定义)我有这个:

   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 在应用层定义:

 public interface IConnectionStringProvider
 {
     string GetConnectionString();
 }

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

services.AddDbContext<ContractsWorkloadContext>();

如果我以以下方式覆盖 OnModelCreatingMethod,我可以让它正常工作。

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

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

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

我通过注册 IConnectionStringProvider 接口和实现以及使用属性“Autowired”注册 Context 类来尝试 Autofac 属性注入。但该属性始终为空。

是的,我知道上面是一个字段,而不是一个属性。我试图修改上下文类以具有属性而不是字段。我什至尝试创建一种方法来设置字段并使用 autofac 的方法注入。但是在每种情况下,属性/字段始终为空。

 builder.RegisterType<ConnectionStringProvider>().As<IConnectionStringProvider>()();
 builder.RegisterType<MyContext>().PropertiesAutowired();

 builder.RegisterType<ContractsWorkloadContext>().OnActivated(e =>
 {
     var provider = e.Context.Resolve<IConnectionStringProvider>();
     e.Instance.SetConnectionstringProvider(provider);
 });

总之,我需要:

  1. 将连接字符串注入上下文
  2. 允许创建空的构造函数实例
  3. 保持“清洁架构”设计

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

谢谢。

4

2 回答 2

0

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

通过这样做,我能够在应用层抽象 IConnectionStringProvider 并在基础设施层实现它。如果需要,这将允许以最小的努力换出实现。

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

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

数据库上下文

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

设置静态值

这绝对有效......但如果有更好的方法,那么我会全神贯注...... :)

于 2019-03-29T00:46:58.190 回答
-1

这是一个更好的方法......对于任何偶然发现这个的人......

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

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

EFCustomerRepository : EFRepository<MyContext, Customer>

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

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

于 2020-03-23T15:49:20.093 回答