簡體   English   中英

動態ConnString對DbContext的依賴注入

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM