StructureMap、NHibernate 和多个数据库

2023-12-26

我正在使用 Fluent NHibernate 开发 Asp.Net MVC 3 应用程序。我只是尝试使用 StructureMap 添加 IoC 容器。

我已经实现了一个自定义控制器工厂,它使用 StructureMap 来创建控制器并注入依赖项。每个控制器构造函数都采用一个或多个服务,而这些服务又采用 DAO 作为构造函数参数。每个 DAO 构造函数都采用一个 ISessionFactory。

对于我的 StructureMap NHibernate 注册表,我有以下内容:

internal class NHibernateRegistry : Registry
{
    public NHibernateRegistry()
    {
        var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;

        For<ISessionFactory>()
                .Singleton()
                .Use(x => new AppSessionFactory().GetSessionFactory(connectionString));

        For<ISession>()
            .HybridHttpOrThreadLocalScoped()
            .Use(x => x.GetInstance<ISessionFactory>().OpenSession());
    }

}

public class AppSessionFactory
{
    public ISessionFactory GetSessionFactory(string connectionString)
    {
        return GetConfig(connectionString)
                .BuildSessionFactory();
    }

    public static FluentConfiguration GetConfig(string connectionString)
    {
        return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2005.ConnectionString(x => x.Is(connectionString)))
            .Mappings(
                x => x.FluentMappings.AddFromAssemblyOf<AppEntity>());
    }
}

对于单个数据库和单个会话工厂来说,这一切都可以正常工作。然而,该应用程序使用多个数据库。

处理这个问题的最佳方法是什么?


注册多个会话工厂很容易 - 问题是在需要时选择正确的会话工厂。例如,假设我们有一个拥有多个数据库的实验室。每个实验室都有一个位置和该位置的多个样本。我们可以有一个 SampleRepository 来模拟它。每个位置都有一个唯一的密钥来识别它(例如“LabX”、“LabY”、“BlackMesa”)。我们可以使用该唯一键作为 app.config 文件中数据库连接字符串的名称。在此示例中,我们将在 app.config 文件中包含三个连接字符串。这是一个示例 connectionStrings 部分:

<connectionStrings>
  <add name="LabX" connectionString="Data Source=labx;User ID=someuser;Password=somepassword"/>
  <add name="LabY" connectionString="Data Source=laby;User ID=someuser;Password=somepassword"/>
  <add name="BlackMesa" connectionString="Data Source=blackmesa;User ID=freemang;Password=crowbar"/>
</connectionStrings>

因此,我们需要为每个连接字符串拥有一个唯一的会话工厂。让我们创建一个包装 ISessionFactory 的 NamedSessionFactory:

public interface INamedSessionFactory
{
    public string Name { get; } // The name from the config file (e.g. "BlackMesa")
    public ISessionFactory SessionFactory { get; }
}

public class NamedSessionFactory : INamedSessionFactory
{
    public string Name { get; private set; }
    public ISessionFactory SessionFactory { get; private set; }

    public NamedSessionFactory(string name, ISessionFactory sessionFactory)
    {
        Name = name;
        SessionFactory = sessionFactory;
    }
}

现在我们需要稍微修改一下你的AppSessionFactory。首先,您创建的是一个会话工厂 - 这并不是我们正在寻找的。我们想要给我们的工厂一个位置并从中获取一个会话,而不是一个会话工厂。 Fluent NHibernate 为我们提供了会话工厂。

public interface IAppSessionFactory
{
    ISession GetSessionForLocation(string locationKey);
}

这里的技巧是在构造函数中接受 INamedSessionFactory 对象的列表。 StructureMap 应该为我们提供我们已注册的所有 INamedSessionFactory 对象。我们稍后会进行注册。

public class AppSessionFactory : IAppSessionFactory
{
    private readonly IList<INamedSessionFactory> _factories;

    public AppSessionFactory(IEnumerable<INamedSessionFactory factories)
    {
        _factories = new List<INamedSessionFactory>(factories);
    }

这就是奇迹发生的地方。给定一个位置键,我们遍历工厂列表,寻找与 locationKey 名称相同的工厂,然后要求它打开一个会话并将其返回给调用者。

    public ISession GetSessionForLocation(string locationKey)
    {
        var sessionFactory = _factories.Where(x => x.Name == locationKey).Single();

        return sessionFactory.OpenSession();
    }
}

现在让我们把这一切连接在一起。

internal class NHibernateRegistry : Registry
{
    public NHibernateRegistry()
    {

我们将循环遍历 app.config 文件中的所有连接字符串(本示例中将包含三个连接字符串),并为每个连接字符串注册一个 INamedSessionFactory 对象。

        foreach (ConnectionStringSettings location in ConfigurationManager.ConnectionStrings)
        {
            For<INamedSessionFactory>()
                .Singleton()
                .Use(x => new NamedSessionFactory(
                    location.Name,
                    GetSessionFactory(location.ConnectionString));
        }

我们还需要注册IAppSessionFactory。

        For<IAppSessionFactory>()
          .Singleton()
          .Use<AppSessionFactory>();
    }

您会注意到,我们已将此逻辑移出工厂类...这些是从 Fluent NHibernate 创建会话工厂的辅助方法。

    private static ISessionFactory GetSessionFactory(string connectionString)
    {
        return GetConfig(connectionString)
                .BuildSessionFactory();
    }

    public static FluentConfiguration GetConfig(string connectionString)
    {
        return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2005.ConnectionString(x => x.Is(connectionString)))
            .Mappings(
                x => x.FluentMappings.AddFromAssemblyOf<AppEntity>());
    }
}

应该这样做!让我们创建一个存储库来获取我们的示例......

public class SampleRepository
{
    private readonly IAppSessionFactory _factory;

    public SampleRepository(IAppSessionFactory factory)
    {
        _factory = factory;
    }

    public IEnumerable<Sample> GetSamplesForLocation(Location location)
    {
        using (ISession session = _factory.GetSessionForLocation(location.Key)
        {
            foreach (Sample sample in session.Query<Sample>())
              yield return sample;
        }
    }
}

现在,您可以获取 SampleRepository 的单个实例,并使用 GetSamplesForLocation 方法从我们在 app.config 中注册的三个数据库中的任何一个中提取样本。不过可能想避开 BlackMesa。我知道那里存在问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

StructureMap、NHibernate 和多个数据库 的相关文章

  • Asp.Net 捆绑不使用 .min 文件

    根据发布模式下的文档 捆绑程序应该使用 min js 文件 如果存在 我通过以下方式添加角度 bundles Add new ScriptBundle Bundles Scripts Include Content Scripts angu
  • NHibernate、Fluent NHibernate 和 Iesi.Collection 的问题。接下来你会尝试什么?

    我对 NHibernate 非常陌生 所以如果我在这里遗漏了一些琐碎的事情 我深表歉意 我目前正在阅读 packtpub 出版的一本名为 NHibernate 3 Beginners Guide 的书 我基本上都是按照书中的指示进行的 当我
  • 尝试通过安全透明方法 xxx 访问安全关键 yy

    我刚刚开始学习 ASP NET MVC 并遵循 ASP NET MVC 教程 我正在使用 Visual Studio Express 2013 RC for Web 认为这可能是我的问题的原因 因为分页教程是使用 VS2012 编写的 一切
  • mvc 登录尝试失败后生成验证码

    所以我能够让我的验证码工作正常工作 但我的问题是 我想让它只在 3 次尝试后出现 我的一个选择是将用户重定向到一个已经有验证码的视图 重复登录 但带有验证码 然后让他通过该页面登录 还有其他选择吗 我觉得部分视图会导致页面发布出现问题 您认
  • 在ConfigureServices中注入依赖

    在我的 ASP Net Core 应用程序中 我需要在以下位置注入一些依赖项 在我的例子中是一个存储库 ConfigureServices method 问题是该方法不允许使用多个参数来注入依赖项 该怎么办呢 这是我的代码 public v
  • 实体类型 ApplicationUser 不是当前上下文模型的一部分。在项目开始时使用了两个不同的数据库

    我使用实体框架创建了一个 MVC 4 应用程序来读取数据并将数据写入我在 Azure 数据库上托管的数据库 Azure 数据库应该保存应用程序数据和应用程序的登录数据 但是 当我第一次创建应用程序时 我忘记删除到本地计算机的连接字符串 因此
  • MVC3 TextBoxFor 带有编码文本

    有没有办法将 TextBoxFor 助手与编码文本一起使用 例如 当使用 MVC3 With Razor 视图引擎的以下帮助程序时 Html TextBoxFor model gt model Description 并且对 model D
  • C# SMTP 身份验证失败,但凭据正确

    这是我的问题 我编写了以下程序来测试是否可以发送电子邮件 class Program static void Main string args try Console WriteLine Mail To MailAddress to new
  • ASP.net MVC 项目无法在 IIS 上编译

    我以前只是将 ASP NET 网站上传到实时服务器 IIS 会自动编译它们 但是 当我对 asp net MVC 项目执行相同操作时 我只是收到错误 并且我需要在上传项目之前发布 构建 项目 注意1 我使用的是VWD 2008 Expres
  • Owin 声明 - 添加多个 ClaimTypes.Role

    我有一个应用程序 可以在其中为用户分配以下角色 超级管理员 Admin User 一个用户可能分配了两个或多个角色 例如 超级管理员和用户 我的应用程序使用声明 因此我也想通过声明来验证用户角色 喜欢 Authorize Roles Adm
  • 具有实体框架的 MVC 控制器的 T4 模板 - 主机的成员属性 (MvcTextTemplateHost)?

    有谁有我可以在 MVC 3 附带的 T4 模板 ControllerWithContext tt 中使用的 Host 对象成员的完整引用吗 我已经尝试了我能想到的所有谷歌搜索 但唯一相关的结果是这个页面 http blogs msdn co
  • ASP.NET MVC 显示配置文件中的用户名

    以下是LogOn来自 Visual Studio 创建的标准默认 ASP NET MVC 项目的用户控件 登录用户控件 ascx Welcome b b
  • 如何为客户端和服务器缓存设置不同的缓存过期时间

    我想让某些页面为客户端提供 10 分钟缓存 为服务器提供 24 小时缓存 原因是如果页面发生变化 客户端将在 10 分钟内获取更新版本 但如果没有任何变化 服务器只需每天重建一次页面 问题在于输出缓存设置似乎覆盖了客户端设置 这是我的设置
  • 带有 HttpContext 的 ASP.NET MVC 单元测试控制器

    我正在尝试为我的一个控制器编写一个单元测试 以验证视图是否正确返回 但该控制器有一个访问 HttpContext Current Session 的基本控制器 每次我创建控制器的新实例时 都会调用 basecontroller 构造函数 并
  • 将多个对象传递给我的控制器

    我将一个对象传递给我的控制器 如下所示 var form JSON stringify subRevisedRequest frmRevised val subSubcontractor frmSubcontractor val subDe
  • MVC 项目中的 .Rdlc 报告 - 托管调试助手“PInvokeStackImbalance”

    我即将完成并运行我的上一份报告 我在其他报告中没有遇到过这个问题 我正在尝试根据数据库记录创建报告 当我通过 LocalReport 创建报告并为报告创建参数时 收到错误消息 托管调试助手 PInvokeStackImbalance 调用
  • 使用 AJAX 加载部分视图不起作用

    请原谅我 我是 MVC 和 AJAX 的新手 目前我只是提交一个表单 我想使用表单中的数据使用 ajax 更新部分视图中的表 My UserInfo部分视图如下所示 model IEnumerable
  • 使用无状态会话延迟查找字典值

    在我的应用程序中 我设置了一个三元字典映射 以便对于给定用户 我可以检索属于该用户的对象的每个实例的 设置 也就是说 我有类似的东西 public class User public virtual IDictionary
  • 无法将 MVC 4 部署到服务器

    我的 Web 应用程序只是一个用 VS 2010 MVC 4 制作的简单 Web 应用程序 没有任何外部代码 它只是 VS 2010 的默认应用程序 我有 Plesk 的豪华 Windows 托管 我从未更改过帐户中的任何功能 我将所有文件
  • 良好的 WiX 编辑器 [重复]

    这个问题在这里已经有答案了 我目前正在开发一个使用 WiX 创建 MSI 的项目 我过去在 Sourceforge 上使用 WiXEdit 来管理包含在 WiX 项目中的文件 因为它比直接操作 XML 稍微容易一些 但它仍然有点笨重 有谁知

随机推荐