代码之家  ›  专栏  ›  技术社区  ›  David Pfeffer

从QueryOver(或者流利的NHibernate)中获得神奇的字符串?

  •  3
  • David Pfeffer  · 技术社区  · 14 年前

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

    遗憾的是,我正在使用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的东西都可能是有益的。

    2 回复  |  直到 14 年前
        1
  •  4
  •   Matan    9 年前

    更新

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


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

    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));
    
        2
  •  0
  •   cdmdotnet    14 年前

    http://nhforge.org/wikis/general/open-source-project-ecosystem.aspx 有很多可能有用的项目。NhGen公司( http://sourceforge.net/projects/nhgen/ )创建非常简单的助手类,这些类可以帮助您找到所需的设计路径。

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

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

    这样,您的魔术字符串就隐藏在其他属性后面(我只是选择了.Abc来演示,但我相信您会对所需内容有更好的了解),然后如果“Abc”更改(比如说“xyz”),您可以将属性名称从.Abc更改为.xyz,然后您将有生成错误来显示您需要更新代码的位置(很像您所做的那样)或者只是将.Abc属性的值改为“xyz”—只有当您的属性有某个有意义的全名(例如.OtherObjectIntersectingColumn等)而不是该属性名本身时,它才真正起作用。这样做的好处是不必更新代码来更正生成错误。此时,您的查询可能

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

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