我尝试使用Net core为CRM应用程序创建API。问题是我不想为CRM的每个客户仅使用一个大型数据库。
我想要的是,对于每个订阅的新客户,我都会使用公司名称生成一个新数据库,因此APi将connectionString与该新数据库一起用于该新公司。 所有客户端都使用相同的身份数据库进行订阅。
EntityFramework和.Net core 3是否可以实现,请问该怎么做? 谢谢:)
答案 0 :(得分:1)
是的,有可能。下面,我在.NetCore(3.0)Web API中创建了一个小示例。这个想法是,您必须在HttpRequest标头中传递公司名称,然后在DbContext类中使用它。这样,您将能够在控制器中获取包含connectionString的DbContext实例,该实例包含新的公司名称,并使用新的公司名称创建新的数据库。
在appsettings.json中创建一个名为sql的节,其中包含connectionString。不要指定数据库名称,并在=
符号后留空:
"sql": {
"connectionString": "Server=localhost;User ID=userId;Password=yourPass;Database="
}
创建一个类SqlSettings
,该类将用于保留connectionString:
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}";
}
}
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);
}
}
在我们的CustomContext
类中,有一个名为Users
的表,它已作为测试用例创建:
public class User
{
public Guid Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
在Startup.cs
方法内的ConfigureServices
类中,我们需要注册我们的类,以便能够使用DI来获取它们。
public void ConfigureServices(IServiceCollection services)
{
......
services.AddHttpContextAccessor();
services.Configure<SqlSettings>(Configuration.GetSection("sql"));
services.AddEntityFrameworkSqlServer().AddDbContext<CustomContext>();
}
现在,我们可以在任何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
将不会再次创建它。
答案 1 :(得分:0)
我会这样:
创建一个存储过程,该过程为您创建新数据库,将新数据库名称以及新客户端/租户需要的任何其他信息作为输入参数。
然后,当您需要创建新数据库时,首先获得EF来调用存储过程,然后创建数据库。
另请参见此处,因为您对如何使用新数据库名称的参数感兴趣: