【问题标题】:How do I use multiple databases with sqlmembershipprovider at runtime?如何在运行时将多个数据库与 sqlmembershipprovider 一起使用?
【发布时间】:2014-05-15 09:23:10
【问题描述】:

我有一个 Web 应用程序和两个 sql 数据库。我的客户想要不同的语言,我已经用资源文件解决了这个问题,这是网站的公共部分之一,没有问题。问题是他们有两个具有相同结构和数据类型但语言不同的数据库,用户也不同。我已将 SqlMembershipProvider 中的“初始化”覆盖为:

public class MyqlMembershipProvider : SqlMembershipProvider
{

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            var connectionString = GetConnectionStringFromSelectedLanguage();

            config["connectionStringName"] = connectionString;
            base.Initialize(name, config);            
        }
}

但是 Initialize 只被调用一次,我每次使用 Membership.yadayada 时都需要设置 connectionString,具体取决于所选的语言。我不想使用Membership.Providers["one_provider"].DeleteUser(a_username),因为它无处不在。我应该怎么做,还有什么我可以覆盖的吗?

/迈克

【问题讨论】:

  • 您是否考虑过从 MembershipProvider 扩展?

标签: c# asp.net sql .net asp.net-mvc


【解决方案1】:

这是不可能的。成员资格提供者是一个静态对象,初始化一次并在用户之间共享。更改它的任何值都会更改应用程序的所有用户。有关更详尽的解释,请参阅此答案...

How do I use multiple databases with sqlmembershipprovider at runtime?

【讨论】:

    【解决方案2】:

    您可以为应用程序使用Ninject 之类的DependencyInjection 框架,并基于命名依赖项构建您的存储库。

    例如,您可以有一个只提供连接字符串名称的接口:

    Interface IConnectionProvider
    {
       ConnectionName { get;}
    }
    
    class LanguageAProvider : IConnectionProvider
    {
        public string ConnectionName { get { return "dbnameLangA"; }  }
    }
    
    class LanguageBProvider : IConnectionProvider
    {
        public string ConnectionName { get { return "dbnameLangB"; }  }
    }
    
    public class MyqlMembershipProvider : SqlMembershipProvider
    {
        private readonly string _connectionStringName;
    
        public MyqlMembershipProvider (IConnectionProvider connection)
        {
            _connectionStringName = connection.ConnectionName;
        }
    
            public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
            {
                var connectionString = GetConnectionStringFromSelectedLanguage();
    
                config[_connectionStringName] = _connectionStringName;//I'm not sure how you need to use the connection name here.
                base.Initialize(name, config);            
            }
    }
    

    我还没有测试过这些,但这可能是一个想法。然后您可以让Named Bindings 在运行时选择所需的依赖项。

    【讨论】:

    • 这行不通,Initialize 只调用一次,并且提供程序在所有语言的用户之间共享。
    • @Joe,我明白了……我不确定那部分。那我就删掉这个答案。
    【解决方案3】:

    我每次使用 Membership.yadayada 时都需要设置 connectionString,具体取决于所选的语言

    这是不可行的:考虑同时处理来自不同语言用户的两个请求时会发生什么。如果您更改了用户 A 的连接字符串,则会影响用户 B。

    您可以做的是编写一个自定义成员资格提供程序,它聚合两个(或更多)SqlMembershipProviders,并根据当前用户的语言进行重定向。

    public class MyMembershipProvider : MembershipProvider
    {
         private Dictionary<string, MembershipProvider> _languageMembeshipProviders;
    
         public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            ... create an SqlMembershipProvider for each language and add to
            ... the languageMembeshipProviders dictionary
        }
    
        public override bool ValidateUser(...)
        {
            ... Get language from HttpContext.Current somehow
            ... select a provider from the dictionary
            ... call the provider
        }
    }
    

    但是我发现很难理解这在实践中是如何工作的。大概请求中有一些东西(查询字符串、cookie、accept-languages 标头)来指示用户的语言。如果是这样,用户可能会使用一种语言进行身份验证,然后通过更改其请求中的语言切换到访问另一个数据库。

    我原以为每种语言都有单独的应用程序会更简单、更简洁。如果用户到达站点 A,表明他想要语言 B,那么他应该被重定向到应用程序 B。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 1970-01-01
      • 2016-07-28
      • 2015-12-19
      • 2021-11-27
      • 2011-12-20
      • 1970-01-01
      相关资源
      最近更新 更多