3

我一直在尝试按照 Hendry Luk 的计算属性解决方案在我的持久层中创建一个计算属性

我可以使用 linq 查询从数据库中选择值:

var result  = from parcel in Repository.Query();

当我尝试对所选结果执行 where 时,出现无法解析属性错误。

这是我的代码的样子。

我的模型:

 namespace ConsoleApplication14
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Linq.Expressions;
        using System.Text;

        public class Common1 : ICommon
        {
            public virtual int Id { get; set; }

            public virtual string Name { get; set; }

            //public static readonly Expression<Func<Common1, string>> CalculatedDisplayExpression = x => ("Common 1 Display: " + x.Id + " - " + x.Name);
            public static readonly Expression<Func<Common1, string>> CalculatedDisplayExpression = x => (x.Id + "");

            private static readonly Func<Common1, string> CalculateDisplay = CalculatedDisplayExpression.Compile();

            public virtual string Display { get { return CalculateDisplay(this); } }
        }
    }

我的接口模型实现:

namespace ConsoleApplication14
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;`enter code here`

    public interface ICommon
    {
        int Id { get; set; }
        string Name { get; set; }
        string Display { get;  }
    }
}

模型映射

namespace ConsoleApplication14
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NHibernate.Mapping.ByCode;
    using NHibernate.Mapping.ByCode.Conformist;

    public class Common1Map : ClassMapping<Common1>
    {
        public Common1Map()
        {
            Id(x => x.Id, map => map.Generator(Generators.Native));
            Property(x => x.Name);
        }
    }
}



namespace ConsoleApplication14
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Text;
    using NHibernate.Hql.Ast;
    using NHibernate.Linq;
    using NHibernate.Linq.Functions;
    using NHibernate.Linq.Visitors;

    public class CalculatedPropertyGenerator<T, TResult> : BaseHqlGeneratorForProperty
    {
        public static void Register(ILinqToHqlGeneratorsRegistry registry, Expression<Func<T, TResult>> property, Expression<Func<T, TResult>> calculationExp)
        {
            registry.RegisterGenerator(ReflectionHelper.GetProperty(property), new CalculatedPropertyGenerator<T, TResult> { _calculationExp = calculationExp });
        }

        private CalculatedPropertyGenerator() { }

        private Expression<Func<T, TResult>> _calculationExp;

        public override HqlTreeNode BuildHql(MemberInfo member, Expression expression, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            return visitor.Visit(_calculationExp);
        }
    }
}


namespace ConsoleApplication14
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NHibernate;
    using NHibernate.Cfg;
    using NHibernate.Cfg.MappingSchema;
    using NHibernate.Dialect;
    using NHibernate.Driver;
    using NHibernate.Tool.hbm2ddl;
    using NHibernate.Mapping.ByCode;
    using NHibernate.Mapping;
    using Iesi.Collections.Generic;
    using System.Reflection;
    using NHibernate.Linq.Functions;
    using NHibernate.Linq;

    public class SessionProvider
    {
        private static ISessionFactory sessionFactory;

        public static SessionProvider Instance { get; private set; }
        //DefaultLinqToHqlGeneratorsRegistry registry = new DefaultLinqToHqlGeneratorsRegistry();

        ILinqToHqlGeneratorsRegistry registry = new DefaultLinqToHqlGeneratorsRegistry();

        static SessionProvider()
        {
            var provider = new SessionProvider();
            provider.Initialize();
            Instance = provider;
        }

        private SessionProvider() { }

        private void Initialize()
        {
            const string connString = "server=(local)\\mssql2008;database=Common;integrated security=sspi";

            Configuration configuration = new Configuration();
            configuration
                .DataBaseIntegration(db =>
                {
                    db.ConnectionString = connString;
                    db.Dialect<MsSql2008Dialect>();
                    db.Driver<SqlClientDriver>();
                    db.LogSqlInConsole = true;
                    db.IsolationLevel = System.Data.IsolationLevel.ReadCommitted;
                })
                .AddDeserializedMapping(GetMappings(), null);


            CalculatedPropertyGenerator<Common1, string>.Register(registry, x => x.Display, Common1.CalculatedDisplayExpression);

//            registry.RegisterGenerator(ReflectionHelper.GetProperty<Common1, string>(x => x.Display), new CalculatedPropertyGenerator());




            var exporter = new SchemaExport(configuration);
            exporter.Execute(true, true, false); 
            sessionFactory = configuration.BuildSessionFactory();
        }

        private HbmMapping GetMappings()
        {
            ModelMapper mapper = new ModelMapper();
            mapper.AddMappings(Assembly.GetAssembly(typeof(Common1Map)).GetExportedTypes());
            HbmMapping mappings = mapper.CompileMappingForAllExplicitlyAddedEntities();

            return mappings;
        }

        public ISession OpenSession()
        {
            return sessionFactory.OpenSession();
        }
    }
}

客户:

namespace ConsoleApplication14
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NHibernate;
    using NHibernate.Linq;
    using NHibernate.Linq.Functions;

    public class Tester
    {
        private ILinqToHqlGeneratorsRegistry registry = new DefaultLinqToHqlGeneratorsRegistry();
        public void Go()
        {
            using (ISession session = SessionProvider.Instance.OpenSession())
            {
                CreateData(session);

                IQueryable<ICommon> commons = session.Query<ICommon>();//.Where(x => x.Display.Contains("Common1 #7"));

                var common1 = session.Query<Common1>().Where(x => x.Display.Contains("Common1 #7"));

                foreach(var common in commons)
                {
                    Console.WriteLine(common.Display);
                }
            }
        }

        private void CreateData(ISession session)
        {
            using (ITransaction tx = session.BeginTransaction())
            {
                for (int i = 0; i < 10; i++)
                {
                    session.SaveOrUpdate(new Common1() { Name = "Common1 #" + i });
                }

                tx.Commit();
            }
        }
    }
}
4

2 回答 2

3

在 SessionProvider 类中注册,例如

configuration.LinqToHqlGeneratorsRegistry<MyLinqToHqlGeneratorsRegistry>(); 

MyLinqToHQLGeneratorRegistry 实现看起来像这样

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Linq.Functions;
using NHibernate.Linq;

namespace ConsoleApplication14
{
    public class MyLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
    {
        public MyLinqToHqlGeneratorsRegistry()
            : base()
        {

            CalculatedPropertyGenerator<Common1, string>.Register(this, x => x.Display, Common1.CalculatedDisplayExpression);
        }
    }
}
于 2013-01-09T18:35:57.220 回答
2

您需要从 DefaultLinqToHqlGeneratorsRegistry 派生一个类。在其构造函数中添加注册逻辑(将“this”传递给CalculatedPropertyGenerator<>.Register())。然后使用 NHibernate 配置注册该类:

cfg.LinqToHqlGeneratorsRegistry<OurLinqFunctionRegistry>();
于 2013-01-04T12:09:44.937 回答