在每次调用的运行时将连接字符串传递给 Entity framework
Passing connection string to Entity framework at runt time for each call
我的Entity framework上下文如下
public partial class MyContext : DbContext, IMyContext
{
static MyContext()
{
System.Data.Entity.Database.SetInitializer<MyContext>(null);
}
public MyContext()
: base("Name=MyContext")
{
}
我是通过autofac通过以下方式解决的
builder.RegisterType(typeof(MainContext)).As(typeof(DbContext)).InstancePerLifetimeScope();
builder.RegisterType<MainContext>().As<IMainContext>().InstancePerRequest();
此数据库上下文在存储库层中被调用
#region Fields
private readonly IMyContext _context;
#endregion
#region Constructors and Destructors
public EmployeeRepository(IMyContext context)
{
_context = context;
}
#endregion
public void Create(Employee emp)
{
this._context.Employee.Add(emp);
}
现在我的问题是,我想在每次调用时动态设置连接字符串。连接字符串将通过我想传递给此上下文的 webapi 传递。谁能帮我我该怎么做?我在这里对 autofac 感到困惑。其次,我如何确保每次调用都设置连接字符串并且不缓存它。
您可以使用一个工厂来构建上下文并为您设置连接字符串。
public interface IContextFactory
{
IContext GetInstance();
}
public class MyContextFactory : IContextFactory
{
public IContext GetInstance()
{
String connectionString = this.GetConnectionString(HttpContext.Current);
return new MyContext(connectionString);
}
private String GetConnectionString(HttpContext context)
{
// do what you want
}
}
builder.RegisterType<MyContextFactory>()
.As<IContextFactory>()
.InstancePerRequest();
builder.Register(c => c.Resolve<IContextFactory>().GetInstance())
.As<IContext>()
.InstancePerRequest();
如果您无法获取基于 HttpContext 的连接字符串,您可以更改 contextFactory 实现以期望在创建实例之前由 WebAPI 进行初始化。例如:
public interface IContextFactory
{
IContext GetInstance();
void Initialize(String connectionString);
}
public class MyContextFactory : IContextFactory
{
private String _connectionString;
public void Initialize(String connectionString)
{
this._connectionString = connectionString;
}
public IContext GetInstance()
{
if (this._connectionString == null)
{
throw new Exception("connectionString not initialized");
}
return new MyContext(this._connectionString);
}
}
在您的网络 API 调用开始时(例如通过属性),您可以调用 Initialize
方法。因为工厂是 InstancePerRequest
,所以在请求期间您将拥有一个实例。
顺便说一句,我不太清楚这个注册
builder.RegisterType(typeof(MainContext)).As(typeof(DbContext)).InstancePerLifetimeScope();
builder.RegisterType<MainContext>().As<IMainContext>().InstancePerRequest();
它看起来有问题,因为您将有 2 个相同类型的不同注册,而不是针对相同的范围,这是有意的吗?此外,注册一个 DbContext
听起来不是个好主意,你需要这个注册吗?
以下注册看起来更好:
builder.RegisterType<MainContext>()
.As<IMainContext>()
.As<DbContext>()
.InstancePerRequest();
我的Entity framework上下文如下
public partial class MyContext : DbContext, IMyContext
{
static MyContext()
{
System.Data.Entity.Database.SetInitializer<MyContext>(null);
}
public MyContext()
: base("Name=MyContext")
{
}
我是通过autofac通过以下方式解决的
builder.RegisterType(typeof(MainContext)).As(typeof(DbContext)).InstancePerLifetimeScope();
builder.RegisterType<MainContext>().As<IMainContext>().InstancePerRequest();
此数据库上下文在存储库层中被调用
#region Fields
private readonly IMyContext _context;
#endregion
#region Constructors and Destructors
public EmployeeRepository(IMyContext context)
{
_context = context;
}
#endregion
public void Create(Employee emp)
{
this._context.Employee.Add(emp);
}
现在我的问题是,我想在每次调用时动态设置连接字符串。连接字符串将通过我想传递给此上下文的 webapi 传递。谁能帮我我该怎么做?我在这里对 autofac 感到困惑。其次,我如何确保每次调用都设置连接字符串并且不缓存它。
您可以使用一个工厂来构建上下文并为您设置连接字符串。
public interface IContextFactory
{
IContext GetInstance();
}
public class MyContextFactory : IContextFactory
{
public IContext GetInstance()
{
String connectionString = this.GetConnectionString(HttpContext.Current);
return new MyContext(connectionString);
}
private String GetConnectionString(HttpContext context)
{
// do what you want
}
}
builder.RegisterType<MyContextFactory>()
.As<IContextFactory>()
.InstancePerRequest();
builder.Register(c => c.Resolve<IContextFactory>().GetInstance())
.As<IContext>()
.InstancePerRequest();
如果您无法获取基于 HttpContext 的连接字符串,您可以更改 contextFactory 实现以期望在创建实例之前由 WebAPI 进行初始化。例如:
public interface IContextFactory
{
IContext GetInstance();
void Initialize(String connectionString);
}
public class MyContextFactory : IContextFactory
{
private String _connectionString;
public void Initialize(String connectionString)
{
this._connectionString = connectionString;
}
public IContext GetInstance()
{
if (this._connectionString == null)
{
throw new Exception("connectionString not initialized");
}
return new MyContext(this._connectionString);
}
}
在您的网络 API 调用开始时(例如通过属性),您可以调用 Initialize
方法。因为工厂是 InstancePerRequest
,所以在请求期间您将拥有一个实例。
顺便说一句,我不太清楚这个注册
builder.RegisterType(typeof(MainContext)).As(typeof(DbContext)).InstancePerLifetimeScope();
builder.RegisterType<MainContext>().As<IMainContext>().InstancePerRequest();
它看起来有问题,因为您将有 2 个相同类型的不同注册,而不是针对相同的范围,这是有意的吗?此外,注册一个 DbContext
听起来不是个好主意,你需要这个注册吗?
以下注册看起来更好:
builder.RegisterType<MainContext>()
.As<IMainContext>()
.As<DbContext>()
.InstancePerRequest();