在每次调用的运行时将连接字符串传递给 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();