[英]Dependency Injection of DbContext with Dynamic ConnString
下面是一個簡單但實用的示例,大致說明了我如何進行依賴注入。 當我的DbContext連接字符串不是動態的時,這非常有用。 即使通過配置文件或其他方式傳遞到工廠,也沒關系,只要一直保持相同即可。
我需要圍繞如何對以下代碼進行修改(最好是較小的修改),以允許在運行時動態確定連接字符串。
例如,在“視圖”上說,用戶不僅可以選擇要傳遞到控制器的Post方法中的老師,還可以選擇學校。 如果為了簡單起見,有2個學校具有完全相同的數據庫結構,但是具有不同的連接字符串,如何將其從控制器下放到工廠?
我已經嘗試過在方法之間傳遞值,但是對於大型項目而言,這實際上是不可持續的,增加了出錯的可能性,並且總體上來說,像這樣逐層傳遞某些東西是混亂的(除了違反SOLID) 。 (如果需要,我可以添加我所做的不完全理想的嘗試,為簡潔起見,我將其省略了,因為這已經是一個相當長的問題,對代碼示例和所有內容而言都是如此)。
調節器
public class HomeController : Controller
{
private readonly IDataService _dataService;
public HomeController(IDataService dataService)
{
_dataService = dataService;
}
public ActionResult Index()
{
var results = _dataService.GetTeachers();
var model = new ViewModel
{
Teachers = results
};
return View(model);
}
[HttpPost]
public ActionResult Index(ViewModel model)
{
var results = _dataService.GetCourses(model.Teacher);
model.Courses = new List<string>(results);
return View(model);
}
}
服務
public class DataService : IDataService
{
private readonly IDataRepo _dataRepo;
public DataService(IDataRepo dataRepo)
{
_dataRepo = dataRepo;
}
public List<string> GetCourses(string teacherName)
{
return _dataRepo.GetCourses()
.Where(c => c.Teacher.FirstName == teacherName)
.Select(c => c.Name)
.ToList();
}
public List<string> GetTeachers()
{
return _dataRepo.GetCourses()
.Select(c => c.Teacher.FirstName)
.ToList();
}
}
知識庫
public class DataRepo : IDataRepo
{
private readonly SchoolContext _context;
public DataRepo()
{
_context = ContextFactory.MakeContext();
}
public IEnumerable<Course> GetCourses()
{
return _context.Courses;
}
}
上下文工廠
public static class ContextFactory
{
public static SchoolContext MakeContext()
{
var connString =
"connStringA";
return new SchoolContext(connString);
}
}
UnityConfig
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IDataService, DataService>();
container.RegisterType<IDataRepo, DataRepo>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
首先,您必須決定如何獲取當前使用的連接字符串。 通過URL嗎? 或使用當前用戶或其他任何方式。
然后,創建另一個數據庫,該數據庫在連接字符串和您選擇的方法(用戶,URL ...)之間具有映射
最后,實現一種從數據庫獲取記錄的方法。
因此,假設您將URL用作當前租戶的標識符,則您的實體類應如下所示:
public class Tenant
{
public string Url {get;set;}
public string ConnectionString {get;set;}
}
表示獲取當前租戶的邏輯的接口:
public interface ICurrentTenantService
{
Tenant GetCurrentTenant();
}
現在您將執行它
public class CurrentTenantService : ICurrentTenantService
{
public Tenant GetCurrentTenant()
{
string currentUrl = HttpContext.Current.Url; //make sure to get only the base URL here
return TenantDbContext.Tenants.FirstOrDefault(t=>t.Url == url); //TenantDbContext should be a class that has the Tenant entity
}
}
現在,您必須像這樣將上下文工廠連接到租戶服務
public static class ContextFactory
{
private readonly ICurrentTenantService currentTenantService;
//Inject it in the constructor
public static SchoolContext MakeContext()
{
var currentTenant= currentTenantService.GetCurrentTenant(); //Check for NULL
return new SchoolContext(currentTenant.ConnectionString);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.