如何通过具有Net core 3和Entity Framework的新客户端创建新数据库?

问题描述 投票:0回答:2

我尝试使用Net core为CRM应用程序创建API。问题是我不想为CRM的每个客户端仅使用一个大型数据库。

  • 我必须迁移才能创建数据库
  • 我有一个很大的ApplicationDBContext和许多模型

[我想要的是,对于每个订阅的新客户,我都会使用公司名称生成一个新数据库,因此APi将connectionString与该新数据库一起用于该新公司。所有客户端使用相同的身份数据库进行订阅。

EntityFramework和.Net core 3是否可能,请问该怎么做?谢谢:)

c# asp.net api asp.net-core .net-core
2个回答
1
投票

是的,有可能。下面,我在.NetCore(3.0)Web API中创建了一个小示例。这个想法是,您必须在HttpRequest标头中传递公司名称,然后在DbContext类中使用它。这样,您将能够在控制器中获取包含connectionString的DbContext实例,该实例包含新的公司名称,并使用新的公司名称创建新的数据库。

  1. 在appsettings.json中,创建一个名为sql的节,其中包含connectionString。不要指定数据库名称,并在=符号后将其留空:

    "sql": { "connectionString": "Server=localhost;User ID=userId;Password=yourPass;Database=" }

  2. 创建将用于保留connectionString的类SqlSettings

    public class SqlSettings
    {
      public string ConnectionString { get; set; }
    
      public void SetDbName(string companyName)
      {
          int index = ConnectionString.LastIndexOf("=");
    
          if (index > 0)
              ConnectionString = ConnectionString.Substring(0, index);
    
          ConnectionString = $"{ConnectionString}={companyName}";
      }
    }
    
  3. CustomContext类,它使用依赖注入在其构造函数中获取必要的依赖,并更改connectionString:

    public class CustomContext : DbContext
    {
    
        public string CompanyName { get; private set; }
    
        private IOptions<SqlSettings> _sqlSettings;
    
        public CustomContext(DbContextOptions<CustomContext> options, IOptions<SqlSettings> sqlSettings, IHttpContextAccessor httpContextAccessor)
          : base(options)
        {
          GetDbName(httpContextAccessor.HttpContext.Request);
    
          if (string.IsNullOrEmpty(CompanyName))
              return;
    
          sqlSettings.Value.SetDbName(CompanyName);
    
          _sqlSettings = sqlSettings;
        }
    
        private void GetDbName(HttpRequest httpRequest)
        {
          try
          {
              CompanyName = httpRequest.Headers["CompanyName"];
          }
          catch (Exception)
          {
              CompanyName = "";
          }
        }
    
        public DbSet<User> Users { get; set; }
    
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
          optionsBuilder.UseSqlServer(_sqlSettings.Value.ConnectionString);
        }
    } 
    
  4. 在我们的CustomContext类中,有一个名为Users的表,它已经作为测试用例创建:

    public class User
    {
        public Guid Id { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
    }
    
  5. Startup.cs方法内的ConfigureServices类中,我们需要注册我们的类,以便能够使用DI来获取它们。

    public void ConfigureServices(IServiceCollection services)
    {
        ......
    
        services.AddHttpContextAccessor();
        services.Configure<SqlSettings>(Configuration.GetSection("sql"));
        services.AddEntityFrameworkSqlServer().AddDbContext<CustomContext>();
    }
    
  6. 现在,我们可以在任何CustomContext中使用我们的Controller类,并使用Action's将其作为Action Method Injection参数:

    [HttpGet()]
    public IActionResult Get([FromServices] CustomContext dbContext)
    {
        if (!string.IsNullOrEmpty(dbContext.CompanyName))
            dbContext.Database.EnsureCreated();
    
        return Ok();
    }
    

因此,我们可以创建一个新的数据库作为公司名称,该数据库是从每个HttpRequest's标头中提取的。另外,如果已经存在具有相同公司名称的数据库,则Entity Framework将不会再次创建它。


0
投票

我会这样做:

创建一个存储过程,为您创建新数据库,将新数据库名称以及新客户端/租户需要的任何其他信息作为输入参数。

然后,当您需要创建新数据库时,首先获得EF来调用存储过程,然后创建数据库。

也请参见此处,因为您对如何使用新数据库名称的参数感兴趣:

SQL Server: use parameter in CREATE DATABASE

© www.soinside.com 2019 - 2024. All rights reserved.