使用 .NETCore 对 DAL 和连接字符串进行依赖注入 [英] Dependency Injection with .NETCore for DAL and connection string

查看:16
本文介绍了使用 .NETCore 对 DAL 和连接字符串进行依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不熟悉 .NETCore 的 DI 模式,但无法将连接字符串连接到 DAL.

我遵循了 此主题 通过接受的答案和后续评论.

这是我的基类

公共类 BaseRepository : IRepository{私有只读 IConfiguration 配置;公共 BaseRepository(IConfiguration 配置){this.config = config;}公共字符串 GetSQLConnectionString(){返回配置[数据:默认连接:连接字符串"];}

这是继承基类的存储库类的片段

public class PrivacyLevelRepository : BaseRepository, IRepository{公共 PrivacyLevelRepository(IConfiguration config) : base(config) { }公共无效添加(PrivacyLevelDM 数据模型){...}}

这是在我的startup.cs中

public void ConfigureServices(IServiceCollection services){//添加框架服务.服务.AddMvc();services.AddScoped>(c => new BaseRepository(Configuration));}

但是,在我的服务层中,存储库类的实例化仍然要求将(IConfiguration config)作为参数传递.

 PrivacyLevelRepository repo = new PrivacyLevelRepository();

如何将 IConfiguration 直接加载到我的 DAL,而不必从 Controller > BLL > DAL 传递它.这似乎非常低效,而且不正确.因为 DAL 应该确定对象的连接,而不是控制器或服务层.他们应该不知道数据源,不是吗?

我认为这很简单,我只是在 DI/IoC 范式中没有看到,但我无法弄清楚.

我没有使用实体框架,而是使用自定义数据层.

感谢您的帮助.

解决方案

您可以按照 选项模式 与配置框架.这允许您定义一个自定义类型,用于保存您的配置设置(静态类型),同时仅限于您的实际相关配置.

你可以这样使用它:

public void ConfigureServices(IServiceCollection services){//将 `Data:DefaultConnection` 配置部分注册为//`DatabaseOptions` 类型的配置services.Configure(Configuration.GetSection("Data:DefaultConnection"));//注册您的数据库存储库//请注意,我们不使用我们自己创建对象的自定义工厂services.AddScoped, BaseRepository>();}

这假定一个类型 DatabaseOptions 像这样:

公共类 DatabaseOptions{公共字符串 ConnectionString { 获取;放;}}

然后,您可以将 DatabaseOptions 注入到您的 BaseRepository 中:

公共类 BaseRepository{私有只读 DatabaseOptions _options;公共 BaseRepository(IOptions databaseOptions){_options = databaseOptions.Value;}}

当然,如果你有那个 BaseRepository 的子类型,你也需要注册它们并将选项传递给基类:

//在`ConfigureServices` 方法中也注册存储库services.AddScoped();

public class PrivacyLevelRepository : BaseRepository, IRepository{public PrivacyLevelRepository(IOptionsdatabaseOptions):基础(数据库选项){ }}

<小时><块引用>

我正在像往常一样实例化和使用 repo.我不确定如何使用我没有实例化的类.我如何让这个对象知道它依赖于 PrivacyLevelRepository?

PrivacyLevelRepository repo = new PrivacyLevelRepository();returnValue = repo.GetAllByDomainID(DomainID).ToList();返回返回值;

您似乎还不了解依赖注入背后的想法.依赖注入及其基本原则 控制反转 简单地说就是避免使用 new 创建对象.而不是主动依赖实现(在你的例子中是PrivacyLevelRepository),你放弃了责任,只依赖外部系统为你提供你需要的依赖项.

因此,您不必创建一个新的PrivacyLevelRepository,而是注入一个由其他地方创建的实例.这与您的依赖项的实现松散了耦合.一个非常实际的例子是 PrivacyLevelRepository 如何依赖于 IOptions.作为该存储库的使用者,您无需关心如何获取这样的对象以创建存储库实例.您甚至不需要一开始就知道如何创建存储库实例.

因此您的 PrivacyLevelRepository 使用者应该遵循与存储库本身相同的想法:存储库不知道如何获取这些数据库选项;它只取决于传递这样一个对象的构造实体.你的消费者,我假设一个控制器,应该做同样的事情:

公共类 MyController{私有只读 PrivacyLevelRepository _privacyLevelRepository;public MyController(PrivacyLevelRepositoryprivacyLevelRepository){//而不是*创建*一个存储库,我们只是希望得到一个_privacyLevelRepository =privacyLevelRepository;}公共 IActionResult SomeRoute(){var domainId = "随便";var data = _privacyLevelRepository.GetAllByDomainID(domainId).ToList();返回视图(数据);}}

当然,something 必须在某个时候创建​​依赖项.但是,如果您完全接受依赖注入——ASP.NET Core 不仅非常容易,而且还积极要求你这样做才能完全工作——那么你就不需要关心那部分.您只需在 ConfigureServices 方法中注册类型,然后期望依赖项在您需要的地方得到满足.

有关更多信息,您一定要查看依赖注入文档的章节.

I am new to the DI patterns with .NETCore, and I am having trouble getting my connection strings to my DAL.

I followed the advice given in this thread via the accepted answer, and subsequent comments.

This is my base class

public class BaseRepository : IRepository<IDataModel>
{
    private readonly IConfiguration config;

    public BaseRepository(IConfiguration config)
    {
        this.config = config;
    }

    public string GetSQLConnectionString()
    {
        return config["Data:DefaultConnetion:ConnectionString"];
    }

This is a snippet of a repository class inheriting the base class

public class PrivacyLevelRepository : BaseRepository, IRepository<PrivacyLevelDM>
{
    public PrivacyLevelRepository(IConfiguration config) : base(config) { }
    public void Add(PrivacyLevelDM dataModel)
    {
         ...
    }
}

This is in my startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();
        services.AddScoped<IRepository<IDataModel>>(c => new BaseRepository(Configuration));
    }

However, In my service layer, the instantiation of the repository class is still asking for the (IConfiguration config) to be passed as a parameter.

 PrivacyLevelRepository repo = new PrivacyLevelRepository();

How do I get the IConfiguration loaded directly to my DAL, without having to pass it from Controller > BLL > DAL. This seems extremely inefficient, and incorrect. As the DAL should be determining the connection for an object, not the controller or service layer. They should be agnostic of the datasource, no?

I figure this is something simple, that I am just not seeing within the DI/IoC paradigm, but I cannot figure it out.

Edit: I am not using Entity Framework, but a custom Data layer.

Thanx for any help.

解决方案

You could follow the options pattern with the configuration framework. This allows you to define a custom type that hold your configuration settings (statically typed) while being restricted to only your actual relevant configuration.

You can use it like this:

public void ConfigureServices(IServiceCollection services)
{
    // register the `Data:DefaultConnection` configuration section as
    // a configuration for the `DatabaseOptions` type
    services.Configure<DatabaseOptions>(Configuration.GetSection("Data:DefaultConnection"));

    // register your database repository
    // note that we don’t use a custom factory where we create the object ourselves
    services.AddScoped<IRepository<IDataModel>, BaseRepository>();
}

This assumes a type DatabaseOptions like this:

public class DatabaseOptions
{
    public string ConnectionString { get; set; }
}

Then, you can just have the DatabaseOptions injected into your BaseRepository:

public class BaseRepository
{
    private readonly DatabaseOptions _options;

    public BaseRepository(IOptions<DatabaseOptions> databaseOptions)
    {
         _options = databaseOptions.Value;
    }
}

Of course, if you have subtypes of that BaseRepository, you need to register those as well and pass the options to the base class:

// register the repository as well in the `ConfigureServices` method
services.AddScoped<PrivacyLevelRepository>();

public class PrivacyLevelRepository : BaseRepository, IRepository<PrivacyLevelDM>
{
    public PrivacyLevelRepository(IOptions<DatabaseOptions> databaseOptions)
        : base(databaseOptions)
    { }
}


I am instantiating and using the repo like I always have. I am not sure how to use a class that I don't instantiate. How do i let this object know it depends on the PrivacyLevelRepository?

PrivacyLevelRepository repo = new PrivacyLevelRepository();
returnValue = repo.GetAllByDomainID(DomainID).ToList();
return returnValue;

You do not appear to understand the idea behind dependency injection yet. Dependency injection with its underlying principle Inversion of Control is simply said about avoiding the use of new to create objects. Instead of actively depending on an implementation (in your example the PrivacyLevelRepository), you are giving up the responsibility and just depend on the outer system to provide you with the dependencies you need.

So instead of creating a new PrivacyLevelRepository, you inject an instance that is created by something somewhere else. That looses coupling on the implementation of your dependency. A very practical example of this is how PrivacyLevelRepository depends on IOptions<DatabaseOptions>. You, as a consumer of that repository, should not need to care to know how to get such an object to be able to create the repository instance. You shouldn’t even need to know how to create a repository instance in the first place.

So your consumer of PrivacyLevelRepository should follow the same idea as the repository itself: The repository does not know how to get those database options; it just depends on the constructing entity to pass such an object on. And your consumer, I assume a controller, should do the same:

public class MyController
{
    private readonly PrivacyLevelRepository _privacyLevelRepository;

    public MyController(PrivacyLevelRepository privacyLevelRepository)
    {
         // instead of *creating* a repository, we just expect to get one
         _privacyLevelRepository = privacyLevelRepository;
    }

    public IActionResult SomeRoute()
    {
         var domainId = "whatever";
         var data = _privacyLevelRepository.GetAllByDomainID(domainId).ToList();
         return View(data);
    }
}

Of course, something has to create the dependencies at some point. But if you embrace dependency injection completely—which ASP.NET Core not only makes very easy but also actively requires you to do so in order to work completely—then you don’t need to care about that part. You just register the types in the ConfigureServices method and then expect the dependencies to be fulfilled where you need them.

For more information, you should definitely check out the dependency injection chapter of the documentation.

这篇关于使用 .NETCore 对 DAL 和连接字符串进行依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆