Entity framework 使用实体框架、依赖项注入、工作单元和存储库模式在运行时注入/管理更改连接字符串
形势 我正在使用标题中提到的技术构建一个web应用程序。该应用程序将类似于用于多个客户端的CMS系统。客户端必须使用其公司名和登录凭据登录到此系统。 通过提供的companyname,我连接到一个数据库(静态DbContext,每次都是相同的connectionstring),其中存储了所有客户机的数据库信息,并搜索这个客户机特定的数据库(每个客户机都有自己的完全相同的设计)登录信息。一切正常。 现在是棘手的部分。要继续登录过程,我需要以某种方式使用other DbContext注入或延迟加载存储库,该存储库带有根据另一个数据库的结果构建的连接字符串 我拥有的 从现有数据库生成2个数据库上下文,一个是静态的,一个是动态的(如果可能) 然后上课。通用存储库类/接口Entity framework 使用实体框架、依赖项注入、工作单元和存储库模式在运行时注入/管理更改连接字符串,entity-framework,dependency-injection,repository-pattern,autofac,unit-of-work,Entity Framework,Dependency Injection,Repository Pattern,Autofac,Unit Of Work,形势 我正在使用标题中提到的技术构建一个web应用程序。该应用程序将类似于用于多个客户端的CMS系统。客户端必须使用其公司名和登录凭据登录到此系统。 通过提供的companyname,我连接到一个数据库(静态DbContext,每次都是相同的connectionstring),其中存储了所有客户机的数据库信息,并搜索这个客户机特定的数据库(每个客户机都有自己的完全相同的设计)登录信息。一切正常。 现在是棘手的部分。要继续登录过程,我需要以某种方式使用other DbContext注入或延迟加载存
public interface IRepository
{
void Submit();
}
public interface IRepository<TEntity, TContext> : IRepository
where TEntity : class
where TContext : DbContext
{
//crud stuff
}
public abstract class GenericRepository<TEntity, TContext> : IRepository<TEntity, TContext>
where TEntity : class
where TContext : DbContext
{
private TContext _dataContext;
private IUnitOfWork _unitOfWork;
private readonly IDbSet<TEntity> dbset;
protected GenericRepository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_unitOfWork.Register(this);
}
}
最后是实现该服务并在登录操作中使用该服务的控制器
public class AccountController : BaseController
{
IConnectionService _connectionService;
IEmployeeLoginService _employeeService;
public AccountController(IConnectionService connectionService, IEmployeeLoginService employeeService)
{
_connectionService = connectionService;
_employeeService = employeeService;
}
[AllowAnonymous, HttpPost]
public ActionResult Login(LoginModel login)
{
if ((Settings)Session["Settings"] == null)
{
Settings settings = new Settings();
settings.company = _connectionService.GetCompanyName(login.CompanyName);
if (settings.company != null)
{
settings.licence = _connectionService.GetLicenceByCompanyID(settings.company.Company_id);
if (settings.licence != null)
{
settings.connectionStringOrName = string.Format(@"Data Source={0};Initial Catalog={1};User ID={2};Password={3};Application Name=EntityFrameworkMUE", settings.licence.WS_DatabaseServer, settings.licence.WS_DatabaseName, settings.licence.WS_DatabaseUID, settings.licence.WS_DatabasePWD);
Session["Settings"] = settings;
settings.user = _employeeService.GetEmployeeByLogin(login.UserName, login.Password);
if (settings.user != null)
{
FormsAuthentication.SetAuthCookie(string.Format("{0},{1}", settings.company.Company_id.ToString(), settings.user.Medewerker_ID.ToString()) , login.RememberMe);
return RedirectToAction("index", "home");
}
}
}
}
else
{
return RedirectToAction("index", "home");
}
return View();
}
}
当然还有autofac引导程序
private static void SetAutoFacContainer()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerHttpRequest();
builder.RegisterAssemblyTypes(typeof(UserRepository).Assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces().InstancePerHttpRequest();
builder.RegisterAssemblyTypes(typeof(ConnectionService).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces().InstancePerHttpRequest();
builder.Register(c => new HttpContextWrapper(HttpContext.Current)).As<HttpContextBase>().InstancePerLifetimeScope();
builder.RegisterModule(new AutofacWebTypesModule());
builder.Register(att => new AuthorizeFilter(att.Resolve<IConnectionService>(), att.Resolve<IEmployeeLoginService>())).AsAuthorizationFilterFor<Controller>().InstancePerHttpRequest();
builder.RegisterFilterProvider();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
private static void SetAutoFacContainer()
{
var builder=new ContainerBuilder();
RegisterController(Assembly.getExecutionGassembly());
builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).instanceperhtprequest();
RegisterAssemblyTypes(typeof(UserRepository).Assembly)
.Where(t=>t.Name.EndsWith(“存储库”))
.AsImplementedInterfaces().InstancePerHttpRequest();
builder.RegisterAssemblyTypes(typeof(ConnectionService).Assembly)
.Where(t=>t.Name.EndsWith(“服务”))
.AsImplementedInterfaces().InstancePerHttpRequest();
Register(c=>newhttpcontextwrapper(HttpContext.Current)).As().InstancePerLifetimeScope();
RegisterModule(新的AutofacWebTypesModule());
注册(att=>newauthorizefilter(att.Resolve(),att.Resolve()).AsAuthorizationFilterFor().instanceperhtprequest();
builder.RegisterFilterProvider();
IContainer容器=builder.Build();
SetResolver(新的AutofacDependencyResolver(容器));
}
我的想法是如何做到这一点,在从存储信息的静态数据库中检索数据后,使用连接字符串设置会话变量,并将会话注入到工作单元中,然后以某种方式在那里使用它,但我不能对此束手无策
问题
我是否正朝着正确的方向努力实现这一目标,或者甚至可能实现这一目标?如果没有,您将采取什么步骤来实现这一目标
我知道这是一本很长的书,我希望你们能帮助我,我是一个很新的使用这些技术的人。提前谢谢,我真的很感激 你的方法是正确的,我用过
var mtc = new MultitenantContainer(container.Resolve<ITenantIdentificationStrategy>(), container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc));
然后将以下内容添加到autofact设置中:
var s = c.Resolve<ITenantIdentificationStrategy>();
object id;
if (s.TryIdentifyTenant(out id) && id != null)
{
return id;
}
return "default";
}).Keyed<string>("CompanyName");
builder.Register<Settings>(c =>
{
var companyName = c.ResolveKeyed<string>("companyName");
if (companyName == "default")
{
return new DefaultSettings();
}
var settings = new Settings();
return settings;
}).InstancePerLifetimeScope();
var s=c.Resolve();
对象id;
如果(s.tryiIdentityEnablent(输出id)&&id!=null)
{
返回id;
}
返回“默认”;
}).Keyed(“公司名称”);
builder.Register(c=>
{
var companyName=c.resolvedkeyed(“companyName”);
如果(公司名称==“默认值”)
{
返回新的DefaultSettings();
}
变量设置=新设置();
返回设置;
}).InstancePerLifetimeScope();
您可以解析这些代码块中的内容。我可能会设置一个键控的默认设置,然后当用户登录时,设置将切换到他们的设置,应用程序的其余部分将正常工作。最新文档。非常感谢你花时间回答我的问题,与此同时,我用不同的方式处理了这些问题,但我肯定会按照你的方式重新编码,因为这是更优雅的方式。
private static void SetAutoFacContainer()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerHttpRequest();
builder.RegisterAssemblyTypes(typeof(UserRepository).Assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces().InstancePerHttpRequest();
builder.RegisterAssemblyTypes(typeof(ConnectionService).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces().InstancePerHttpRequest();
builder.Register(c => new HttpContextWrapper(HttpContext.Current)).As<HttpContextBase>().InstancePerLifetimeScope();
builder.RegisterModule(new AutofacWebTypesModule());
builder.Register(att => new AuthorizeFilter(att.Resolve<IConnectionService>(), att.Resolve<IEmployeeLoginService>())).AsAuthorizationFilterFor<Controller>().InstancePerHttpRequest();
builder.RegisterFilterProvider();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
var mtc = new MultitenantContainer(container.Resolve<ITenantIdentificationStrategy>(), container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc));
public class CompanyNameIdentificationStrategy : ITenantIdentificationStrategy
{
public bool TryIdentifyTenant(out object tenantId)
{
var context = HttpContext.Current;
if(context != null)
{
var myUser = context.User as MyUserObject;
if(myUser != null)
{
tenantId = myUser.CompanyName;
return true;
}
}
return false;
}
}
var s = c.Resolve<ITenantIdentificationStrategy>();
object id;
if (s.TryIdentifyTenant(out id) && id != null)
{
return id;
}
return "default";
}).Keyed<string>("CompanyName");
builder.Register<Settings>(c =>
{
var companyName = c.ResolveKeyed<string>("companyName");
if (companyName == "default")
{
return new DefaultSettings();
}
var settings = new Settings();
return settings;
}).InstancePerLifetimeScope();