我需要在我的项目的DbContext类中注入一个依赖项。我正在尝试以一种遵循“干净架构”的方式来做这件事。
我需要能够使用DbContext的空构造函数,同时仍然引用配置文件中的连接字符串。
我利用这个通用存储库并将其注入到服务中。它是在应用层中定义的。
public class GenericRepository<C, T> : IGenericRepository<C, T> where T : class where C : DbContext, new()
{
private DbContext _entities = new C();
}
在我的EF Core上下文类(在持久层中定义)中,我有:
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核心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参数的构造函数。
我唯一要解决的问题是如何在上下文不依赖于实现的情况下实现这一点。
我尝试过Autofac属性注入,方法是注册IConnectionStringProvider接口和实现,以及使用属性“自动连接”注册Context类。但该属性始终为空。
是的,我知道上面是一个字段,而不是一个属性。我尝试修改context类,使其具有属性而不是字段。我甚至尝试创建一个方法来设置字段,并使用带有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);
});
总而言之,我需要:
这里的任何帮助都将不胜感激。
谢谢。
发布于 2020-03-23 23:49:20
这是一种更好的方式。对于那些偶然发现这一点的人..
更具体的存储库实现只是扩展基本存储库实现的类。例如:
EFCustomerRepository : EFRepository<MyContext, Customer>
现在,我可以通过依赖注入在整个应用程序中的任何位置注入IMyEFCoreDatabase
,并引用存储在实现中的存储库。
这是比上面更好的方式,因为我的存储库不再调用new C()。相反,它们现在通过构造函数注入来注入上下文。
发布于 2019-03-29 08:46:58
我最终做的是创建一个对连接字符串的静态引用,然后在返回该值的上下文中创建一个readonly属性。
通过这种方式,我能够在应用层中抽象IConnectionStringProvider并在基础架构层中实现它。这将允许在需要时以最小的努力换出实现。
此外,通过添加返回静态连接字符串的readonly属性,我能够使用利用new()的通用存储库,并且仍然可以从配置文件中获取连接字符串。
这样做的唯一缺点是,连接字符串在整个应用程序生命周期内都存储在内存中。
静态值由提供程序实现在表示层的StartUp.cs文件中设置。
这绝对管用..。但如果有更好的办法我会洗耳恭听。:)
https://stackoverflow.com/questions/55407069
复制相似问题