从 QueryOver(或者 Fluent NHibernate)中获取魔法字符串?

Posted

技术标签:

【中文标题】从 QueryOver(或者 Fluent NHibernate)中获取魔法字符串?【英文标题】:Getting magic strings out of QueryOver (or Fluent NHibernate perhaps)? 【发布时间】:2010-07-29 11:46:32 【问题描述】:

使用 FluentNHibernate、新的 QueryOver API 和新的 Linq 提供程序的众多原因之一都是因为它们消除了“魔术字符串”或表示属性或其他可以在编译时表示的东西的字符串。

遗憾的是,我正在使用 NHibernate 的空间扩展,这些扩展尚未升级为支持 QueryOver 或 LINQ。结果,我不得不使用 QueryOver Lambda 表达式和字符串的组合来表示我想要查询的属性等。

我想做的是——我想要一种方法来询问 Fluent NHibernate(或者可能是 NHibernate QueryOver API)魔术字符串“应该是”什么。这是一个伪代码示例:

目前,我会写 --

var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects("abc", other_object));

我想写的是——

var x = session.QueryOver<Shuttle>().Add(SpatialRestriction.Intersects(session.GetMagicString<Shuttle>(x => x.Abc), other_object));

有这样的东西吗?会不会很难写?

编辑:我只是想指出,这不仅仅适用于空间——实际上任何尚未转换为 QueryOver 或 LINQ 的东西都可能受益。

【问题讨论】:

Fluent NHibernate 与 QueryOver 完全无关;这只是创建映射的另一种方式。 对,但是 Fluent 有能力通过使用 lambdas 消除魔术字符串,就像我想在这里一样。 【参考方案1】:

更新

C# 6 中的 nameof 运算符为此提供了编译时支持。


有一个更简单的解决方案 - 表达式。

举个例子:

public static class ExpressionsExtractor

    public static string GetMemberName<TObj, TProp>(Expression<Func<TObj, TProp>> expression)
    
        var memberExpression = expression.Body as MemberExpression;

        if (memberExpression == null)
            return null;

        return memberExpression.Member.Name;
    

及用法:

var propName = ExpressionsExtractor.GetMemberName<Person, int>(p => p.Id);

ExpressionsExtractor 只是一个建议,您可以将此方法包装在您想要的任何类中,可以作为扩展方法或最好是非静态类。

你的例子可能有点像这样:

var abcPropertyName = ExpressionsExtractor.GetMemberName<Shuttle, IGeometry>(x => x.Abc);
var x = session.QueryOver<Shuttle>().Add(SpatialRestriction.Intersects(abcPropertyName, other_object));

【讨论】:

哦,别忘了给出一个更深思熟虑的解决方案,如果 Body 不是 MemberExpression,这只是一个例子......【参考方案2】:

假设我理解您的问题,您可能想要的每个实体都有一个辅助类,包括列名、属性名和其他有用的东西,特别是如果您想使用 ICriteria 搜索。 http://nhforge.org/wikis/general/open-source-project-ecosystem.aspx 有很多项目可能会有所帮助。 NhGen (http://sourceforge.net/projects/nhgen/) 创建了非常简单的帮助类,它可能会帮助您找到您可能想要的设计路径。

澄清编辑:在“我不明白”评论之后

简而言之,我不相信目前有适合您的解决方案。 QueryOver 项目并没有达到你想要的程度。因此,同时作为一种可能的解决方案,要删除魔术字符串,请构建一个帮助程序类,这样您的查询就变成了

var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects(ShuttleHelper.Abc, other_object));

这样你的魔法字符串就在其他属性的后面(我只是选择 .Abc 来演示,但我相信你会更好地了解你想要什么)然后如果“abc”发生变化(比如“xyz” )您要么将属性名称从 .Abc 更改为 .Xyz ,然后您将遇到构建错误以显示您需要更新代码的位置(就像您使用 lambda 表达式一样),或者只是将 .Abc 属性的值更改为“xyz” - 只有当您的属性有一些有意义的名称(例如 .OtherObjectIntersectingColumn 等)而不是该属性名称本身时,它才会真正起作用。这确实具有不必更新代码来纠正构建错误的优点。那时您的查询可能是

var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects(ShuttleHelper.OtherObjectIntersectingColumn, other_object));

我提到了开源项目生态系统页面,因为它可以为您提供一些关于其他人创建了哪些类型的帮助程序类的指示,这样您就不必重新发明***了。

【讨论】:

我不太明白你的回答...抱歉。 答案已被编辑,因为我无法在评论中为您澄清 这是在编辑之前。无论如何,这不是我真正想要的,但我想它是最好的。

以上是关于从 QueryOver(或者 Fluent NHibernate)中获取魔法字符串?的主要内容,如果未能解决你的问题,请参考以下文章

使用 NHibernate 3.0 QueryOver 或 LINQ 提供程序的权衡

如何使用 NHibernate QueryOver 重新创建这个复杂的 SQL 查询?

在 QueryOver 中

NHibernate 3.0:没有使用QueryOver的FirstOrDefault()?

NHibernate QueryOver 两次加入一个集合

Queryover 的动态 Where 条件