为数据库设定种子时处理依赖项注入

本文关键字:处理 依赖 注入 种子 数据库 | 更新日期: 2023-09-27 18:27:02

我需要为应用程序数据库设置默认用户的种子。我在这个项目中没有使用实体框架,我决定使用Dapper

我能做的最简单的事情就是有一个简单的类,比如DatabaseConfig(或AccountsConfig)和一个Seed()静态方法:

public class DatabaseConfig {
    public static void Seed() {
        using(var conn = new SqlConnection()) {
            conn.ConnectionString = GetConnectionString();
            conn.Open();
            var query = "insert into users (username, [password]) values (@username, @password)";
            var queryParams = new {
                username = "Admin",
                password = HashedPassword.CreateHash("DefaultSecretKey") 
            }
            conn.Execute(query, queryParams);
        }
    }
    private static string GetConnectionString() {
        return ConfigurationManager.ConnectionStrings["appDb"].ConnectionString;
    }
}

然后在Global.asax:中调用它

DatabaseConfig.Seed();

这里有两个依赖项:

  1. 我调用ConfigurationManager来获取连接字符串。我不知道这是不是一个糟糕的方法。对于我在应用程序中使用的其他服务,我将连接字符串作为SimpleInjector初始值设定项中的构造函数参数传递:

    private static void InitializeContainer(Container container) {
        var appDbConnString = ConfigurationManager.ConnectionStrings["appDb"].ConnectionString;
        container.RegisterSingleton<IUsersRepository>(new UsersRepository(appDbConnString));
    }
    
  2. 另一个依赖项是HashedPassword类。我不希望它会随着时间的推移而改变,但这仍然是一种依赖。我应该解决它吗?我该如何解决?

为数据库设定种子时处理依赖项注入

我调用ConfigurationManager来获取连接字符串。我不知道这是不是一个糟糕的方法。

一般情况下,您应该只在应用程序启动时读取配置文件,最好只读取应用程序的启动路径中的配置文件。这允许将配置文件的读取集中在一个地方,并允许应用程序在缺少某些配置值的情况下快速失败。

你似乎遵循了这种做法,所以我认为你所做的一切都很好。

另一个依赖项是HashedPassword类。我不希望它会随着时间的推移而改变,但这仍然是一种依赖。我应该解决它吗?

由于这个Seed方法似乎是您的composition根的一部分,因此可以对系统中的其他类有很强的依赖性。或者让我换一种说法,如果这个依赖项的使用不会以任何方式造成麻烦(因为你不想孤立地测试代码,或者不想替换、包装、装饰或拦截该类中的代码),我会说这没关系。

但是,如果您希望这个HashesPassword类是可注入的,则必须将其作为实例类。在这种情况下,您可能应该将其隐藏在抽象(如IHashPashword)后面,并将其作为参数传递给Seed()方法,或者您应该将DatabaseConfig提升为具有非静态方法的非静态类,并将IHashPashword抽象注入其构造函数。这允许您从容器中解析DatabaseConfig

如果您以静态方式访问HashedPassword和ConfigurationManager,这意味着您需要将它们更改为非静态类,以便依赖注入它们。这可以通过更改它们(这可能是不可能的,因为它们不是您的类)或将它们封装在实例类中来实现。