2013-12-12 1 views
1

У меня есть многозадачное приложение, которое использует одно и то же веб-приложение с несколькими базами данных клиентов и имеющее общий DbContext. Когда пользователь регистрируется на основе своих учетных данных, я предоставляю строку подключения к DbContext и загружаю данные. Проблема возникает, когда одновременно регистрируется несколько пользовательских журналов, и они могут видеть данные друг друга, поскольку DbContext продолжает переключение между разными пользователями.Как использовать совместное использование EF одного DbContext для нескольких баз данных

Я использую EF 5.0 и Autofac IOC в основном. Каков наилучший способ справиться с этим?

Как я могу сохранить свой DbContext свои данные для этого конкретного пользователя и не изменится, даже если другие пользователи вошли в систему и будут иметь разные контексты баз данных для них?

Вот код в моей странице входа

protected void LoginBtn_Click(object sender, EventArgs e) 
    { 
     int i = Convert.ToInt32(CustomerId.Text); 
      var builder = new ContainerBuilder(); 
      var profile = _profileProvider.GetCustomerProfile(i); 
      ConnectionStringManager.ConnectionString = profile.connString; 
      builder.RegisterModule<CustomerDataModule>(); 
      builder.Update(_container); 
      Response.Redirect("Home.aspx"); 
    } 

Это моя статическая переменная, которая дает строку соединения

public static class ConnectionStringManager 
{ 
    public static string ConnectionString { get; set; } 
} 

Вот мой модуль, который имеет все объекты и контекстные классы,

public class CustomerDataModule : Autofac.Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     builder.Register(c => 
     { 
      ConnectionString = ConnectionStringManager.ConnectionString; 

      return new CustomerDataContext(ConnectionString); 
     }) 
     .As<ICustomerDataContext>() 
     .As<IDbContext>() 
     .InstancePerDependency(); 

     builder.RegisterType<CustomerDataContextFactory>().As<ICustomerDataContextFactory>(); 

     var assembly = Assembly.GetExecutingAssembly(); 
     builder.RegisterAssemblyTypes(assembly) 
       .Where(t => t.Name.EndsWith("Repository")) 
       .AsImplementedInterfaces() 
       .InstancePerDependency(); 

    } 
} 

Вот мой DbContext,

public partial class CustomerDataContext: DbContext, ICustomerDataContext 
{ 

    public CustomerDataContext(string connectionString) 
     : base(connectionString) 
    { } 
    ....... 

Вот мой один из репозитория,

public class CustomerRepository : GenericRepository<Customer, int>, ICustomerRepository 
{ 
    public CustomerRepository(ICustomerDataContext context) 
     : base(context, customer => customer.Id) 
    { 
    } 
} 
+0

Вы изучили многоэтажные расширения Autofac, Autofac.Extras.Multitenant.dll? См. Http://code.google.com/p/autofac/wiki/MultitenantIntegration. По крайней мере, вы не можете установить строку подключения в статической переменной, ее нужно вывести из самого контейнера на основе пользовательского контекста запроса. –

+0

Я немного новичок в autofac, я обязательно пойду и изучу расширения с несколькими арендаторами. Можете ли вы показать мне небольшой фрагмент кода, чтобы получить его из контейнера на основе пользовательского контекста, чтобы избежать статической переменной? – rajcool111

ответ

2

статическая переменная в веб-приложение означает предоставлять свои данные между всеми пользователями одновременно. вам нужно перенести это значение в переменную сеанса, которая является конкретной для каждого пользователя.

var builder = new ContainerBuilder(); 
// will add `HTTP request lifetime scoped` registrations (InstancePerHttpRequest) for the HTTP abstraction classes 
builder.RegisterModule(new AutofacWebTypesModule()); 
builder.Register<MyType>(ctx => 
    { 
     var sessionBase = ctx.Resolve<HttpSessionStateBase>(); 
     //now use the session value to retrieve the connection string 
    }); 
+0

Это сработало! Переменная сеанса - это правильный вариант. – rajcool111

+0

Еще одна вещь: я регистрирую свой CustomerDataModule при нажатии кнопки входа в систему, и это звучит немного странно для меня. Как мы делаем это обычно при запуске приложения. Но я не вижу другого варианта, поскольку у меня нет профиля пользователя, чтобы получить информацию о его арендаторе. Можете ли вы дать советы по лучшим вариантам или улучшениям в этом коде? – rajcool111

+0

Вы можете перенести его на Application_Start: http://code.google.com/p/autofac/wiki/WebFormsIntegration – VahidN

Смежные вопросы