【问题标题】:Formula Mapping in NHibernate to Functions in SQLite or Override MappingNHibernate 中的公式映射到 SQLite 中的函数或覆盖映射
【发布时间】:2012-02-28 03:53:57
【问题描述】:

我找到了以下文章 http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx 来帮助我对我的 NHibernate 应用程序进行单元测试。我的大多数测试都运行良好,但抛出了一个奇怪的错误。通过查看生成的 SQL,我相信以下流畅的映射会导致问题:

Map(x => x.IsValid).Formula("CASE WHEN dbo.NumPosts(UserID) = 5 THEN 1 ELSE 0 END");

您会注意到对 dbo.NumPosts 的调用,这是我的数据库中的用户定义函数。我知道还有其他方法可以映射此属性,但这仅用作示例。基本上我需要知道如何使用 SQLite 进行映射。

编辑:

经过进一步思考,是否可以在我的单元测试项目中覆盖该字段的映射?这是我当前的配置:

private static ISessionFactory CreateSessionFactory() {
    return Fluently.Configure()
        .Database(SQLiteConfiguration.Standard.InMemory().ShowSql())
        .Mappings(m => m.FluentMappings
            .AddFromAssembly(typeof(Role).Assembly)
            .Conventions.AddFromAssemblyOf<EnumConvention>())
        .ExposeConfiguration(c => _configuration = c)
        .BuildSessionFactory();
}

我不希望重新定义所有映射,因为这会花费一些时间并且无法维护。

非常感谢您的帮助。谢谢

【问题讨论】:

    标签: nhibernate sqlite fluent-nhibernate


    【解决方案1】:

    参考您评论中的答案,我能够使静态 bool 属性起作用。

    我仍然不喜欢依赖全局布尔变量,所以我决定进一步挖掘。在 NHibernate 3.0 中,他们向 Configuration 对象添加了事件。特别是,我能够利用 Configuration 对象上的新 BeforeBind 事件。

    我稍微重写了您的 CreateSessionFactory() 方法以展示我是如何做到的。

    注意:在我的公式中,我总是将它们写为 dbo.NumPosts,事件处理程序将删除“dbo”。如果我们在 SQLite 方言中运行。

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(SQLiteConfiguration.Standard.InMemory().ShowSql())
            .Mappings(m => m.FluentMappings
                               .AddFromAssembly(typeof (Role).Assembly)
                               .Conventions.AddFromAssemblyOf<EnumConvention>())
            .ExposeConfiguration(c =>
                                     {
                                         c.BeforeBindMapping += BeforeBindMappingHandler;
                                         _configuration = c;
                                     })
            .BuildConfiguration()
            .BuildSessionFactory();
    }
    
    private static void BeforeBindMappingHandler(object sender, BindMappingEventArgs e)
    {
        if (!(e.Dialect is SQLiteDialect)) return;
    
        var properties = e.Mapping.RootClasses
            .SelectMany(r => r.Properties)
            .Where(p => p is HbmProperty)
            .Cast<HbmProperty>()
            .Where(p => p.Formulas.Any());
    
        foreach (var hbmProperty in properties)
            hbmProperty.formula = hbmProperty.formula.ToLower().Replace("dbo.", "");
    }
    

    【讨论】:

      【解决方案2】:

      问题解决了!我可以说:

      [SQLiteFunction(Name = "NumPosts", Arguments = 1, FuncType = FunctionType.Scalar)]
      public class NumPosts : SQLiteFunction {
          public override object Invoke(object[] args) {
              ...
          }
      }
      

      现在我所要做的就是添加一个设置以在我的函数前面添加 dbo 前缀。然后在测试项目中将其设置为空白。

      【讨论】:

      • 您在哪里检测到您正在使用哪种 nhibernate 方言来处理,包括“dbo”。还是不行?
      • 我在 global.asax 文件中设置了一个属性,例如"公共静态字符串 FunctionPrefix = "dbo.";"。然后我在我说“dbo”的任何地方都使用它。在我的公式中。现在在您的测试中,您只需将其设置为一个空字符串。
      猜你喜欢
      • 2011-08-08
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 2012-04-14
      • 2011-08-04
      • 1970-01-01
      • 2021-06-10
      • 2012-02-20
      相关资源
      最近更新 更多