diff --git a/src/NHibernate.Test/CfgTest/ConfigurationFixture.cs b/src/NHibernate.Test/CfgTest/ConfigurationFixture.cs index 3ef285caca0..8403c393130 100644 --- a/src/NHibernate.Test/CfgTest/ConfigurationFixture.cs +++ b/src/NHibernate.Test/CfgTest/ConfigurationFixture.cs @@ -4,10 +4,12 @@ using System.Xml; using NHibernate.Cfg; using NHibernate.DomainModel; +using NHibernate.Engine; +using NHibernate.Linq; using NHibernate.Tool.hbm2ddl; using NHibernate.Util; using NUnit.Framework; -using Environment=NHibernate.Cfg.Environment; +using Environment = NHibernate.Cfg.Environment; namespace NHibernate.Test.CfgTest { @@ -417,5 +419,52 @@ public void NH1348() cfg.Configure(xtr); // No exception expected } + + public class SampleQueryProvider : DefaultQueryProvider + { + public SampleQueryProvider(ISessionImplementor session) : base(session) + { + + } + } + + [Test] + public void NH2890Standard() + { + var cfg = new Configuration(); + cfg.Configure("TestEnbeddedConfig.cfg.xml") + .LinqQueryProvider() + .SetDefaultAssembly("NHibernate.DomainModel") + .SetDefaultNamespace("NHibernate.DomainModel"); + + using (var sessionFactory = cfg.BuildSessionFactory()) + { + using (var session = sessionFactory.OpenSession()) + { + var query = session.Query(); + Assert.IsInstanceOf(typeof(SampleQueryProvider), query.Provider); + } + } + } + + [Test] + public void NH2890Xml() + { + var cfg = new Configuration(); + cfg.Configure("TestEnbeddedConfig.cfg.xml") + .SetDefaultAssembly("NHibernate.DomainModel") + .SetDefaultNamespace("NHibernate.DomainModel"); + + using (var sessionFactory = cfg.BuildSessionFactory()) + { + using (var session = sessionFactory.OpenSession()) + { + var query = session.Query(); + Assert.IsInstanceOf(typeof(SampleQueryProvider), query.Provider); + } + } + + } + } } diff --git a/src/NHibernate.Test/CfgTest/Loquacious/ConfigurationFixture.cs b/src/NHibernate.Test/CfgTest/Loquacious/ConfigurationFixture.cs index f6e0afc42d7..d2d13fa109d 100644 --- a/src/NHibernate.Test/CfgTest/Loquacious/ConfigurationFixture.cs +++ b/src/NHibernate.Test/CfgTest/Loquacious/ConfigurationFixture.cs @@ -8,6 +8,7 @@ using NHibernate.Driver; using NHibernate.Exceptions; using NHibernate.Hql.Ast.ANTLR; +using NHibernate.Linq; using NHibernate.Type; using NUnit.Framework; @@ -124,5 +125,26 @@ public void UseConnectionStringName() Assert.That(cfg.Properties[Environment.ConnectionStringName], Is.EqualTo("MyName")); } + + [Test] + public void NH2890Loquacious() + { + var cfg = new Configuration(); + cfg.Configure("TestEnbeddedConfig.cfg.xml") + .SetDefaultAssembly("NHibernate.DomainModel") + .SetDefaultNamespace("NHibernate.DomainModel") + .SessionFactory() + .ParsingLinqThrough(); + + using (var sessionFactory = cfg.BuildSessionFactory()) + { + using (var session = sessionFactory.OpenSession()) + { + var query = session.Query(); + Assert.IsInstanceOf(typeof(NHibernate.Test.CfgTest.ConfigurationFixture.SampleQueryProvider), query.Provider); + } + } + } + } } \ No newline at end of file diff --git a/src/NHibernate.Test/TestEnbeddedConfig.cfg.xml b/src/NHibernate.Test/TestEnbeddedConfig.cfg.xml index d5bce2e5f2d..25058dae03a 100644 --- a/src/NHibernate.Test/TestEnbeddedConfig.cfg.xml +++ b/src/NHibernate.Test/TestEnbeddedConfig.cfg.xml @@ -7,5 +7,6 @@ Server=localhost;initial catalog=nhibernate;User Id=;Password= true 1, false 0, yes 1, no 0 NHibernate.Dialect.MsSql2000Dialect + NHibernate.Test.CfgTest.ConfigurationFixture+SampleQueryProvider, NHibernate.Test \ No newline at end of file diff --git a/src/NHibernate/Cfg/ConfigurationExtensions.cs b/src/NHibernate/Cfg/ConfigurationExtensions.cs index c07af273e1f..663d5ee15fe 100644 --- a/src/NHibernate/Cfg/ConfigurationExtensions.cs +++ b/src/NHibernate/Cfg/ConfigurationExtensions.cs @@ -3,6 +3,7 @@ using NHibernate.Context; using NHibernate.Engine; using NHibernate.Hql; +using NHibernate.Linq; using NHibernate.Linq.Functions; using NHibernate.Util; @@ -46,6 +47,12 @@ public static Configuration HqlQueryTranslator(this Configurat return configuration; } + public static Configuration LinqQueryProvider(this Configuration configuration) where TQueryProvider : INhQueryProvider + { + configuration.SetProperty(Environment.QueryLinqProvider, typeof(TQueryProvider).AssemblyQualifiedName); + return configuration; + } + public static Configuration LinqToHqlGeneratorsRegistry(this Configuration configuration) where TLinqToHqlGeneratorsRegistry : ILinqToHqlGeneratorsRegistry { configuration.SetProperty(Environment.LinqToHqlGeneratorsRegistry, typeof(TLinqToHqlGeneratorsRegistry).AssemblyQualifiedName); diff --git a/src/NHibernate/Cfg/Environment.cs b/src/NHibernate/Cfg/Environment.cs index 273651148ef..bae74bd511a 100644 --- a/src/NHibernate/Cfg/Environment.cs +++ b/src/NHibernate/Cfg/Environment.cs @@ -141,6 +141,9 @@ public static string Version // The classname of the HQL query parser factory public const string QueryTranslator = "query.factory_class"; + // The class name of the LINQ query provider class, implementing from + public const string QueryLinqProvider = "query.linq_provider_class"; + public const string QueryImports = "query.imports"; public const string Hbm2ddlAuto = "hbm2ddl.auto"; public const string Hbm2ddlKeyWords = "hbm2ddl.keywords"; diff --git a/src/NHibernate/Cfg/Loquacious/FluentSessionFactoryConfiguration.cs b/src/NHibernate/Cfg/Loquacious/FluentSessionFactoryConfiguration.cs index 0c32139850c..f5dc921c471 100644 --- a/src/NHibernate/Cfg/Loquacious/FluentSessionFactoryConfiguration.cs +++ b/src/NHibernate/Cfg/Loquacious/FluentSessionFactoryConfiguration.cs @@ -1,5 +1,6 @@ using NHibernate.Bytecode; using NHibernate.Hql; +using NHibernate.Linq; namespace NHibernate.Cfg.Loquacious { @@ -53,6 +54,13 @@ public IFluentSessionFactoryConfiguration ParsingHqlThrough() return this; } + public IFluentSessionFactoryConfiguration ParsingLinqThrough() + where TQueryProvider : INhQueryProvider + { + configuration.SetProperty(Environment.QueryLinqProvider, typeof(TQueryProvider).AssemblyQualifiedName); + return this; + } + public IProxyConfiguration Proxy { get; private set; } public ICollectionFactoryConfiguration GeneratingCollections { get; private set; } public IMappingsConfiguration Mapping { get; private set; } diff --git a/src/NHibernate/Cfg/Loquacious/IFluentSessionFactoryConfiguration.cs b/src/NHibernate/Cfg/Loquacious/IFluentSessionFactoryConfiguration.cs index cbdea8caa70..23ac2c3abe4 100644 --- a/src/NHibernate/Cfg/Loquacious/IFluentSessionFactoryConfiguration.cs +++ b/src/NHibernate/Cfg/Loquacious/IFluentSessionFactoryConfiguration.cs @@ -1,4 +1,5 @@ using NHibernate.Hql; +using NHibernate.Linq; namespace NHibernate.Cfg.Loquacious { public interface IFluentSessionFactoryConfiguration @@ -26,6 +27,7 @@ public interface IFluentSessionFactoryConfiguration IFluentSessionFactoryConfiguration GenerateStatistics(); IFluentSessionFactoryConfiguration Using(EntityMode entityMode); IFluentSessionFactoryConfiguration ParsingHqlThrough() where TQueryTranslator : IQueryTranslatorFactory; + IFluentSessionFactoryConfiguration ParsingLinqThrough() where TQueryProvider : INhQueryProvider; IProxyConfiguration Proxy { get; } diff --git a/src/NHibernate/Cfg/Settings.cs b/src/NHibernate/Cfg/Settings.cs index 2f8ac968b69..5856837f5f3 100644 --- a/src/NHibernate/Cfg/Settings.cs +++ b/src/NHibernate/Cfg/Settings.cs @@ -100,6 +100,8 @@ public Settings() public IQueryTranslatorFactory QueryTranslatorFactory { get; internal set; } + public System.Type LinqQueryProviderType { get; internal set; } + public ISQLExceptionConverter SqlExceptionConverter { get; internal set; } public bool IsWrapResultSetsEnabled { get; internal set; } diff --git a/src/NHibernate/Cfg/SettingsFactory.cs b/src/NHibernate/Cfg/SettingsFactory.cs index 310b8d874af..f2fc0fea68f 100644 --- a/src/NHibernate/Cfg/SettingsFactory.cs +++ b/src/NHibernate/Cfg/SettingsFactory.cs @@ -2,7 +2,6 @@ using System.Collections; using System.Collections.Generic; using System.Data; - using NHibernate.AdoNet; using NHibernate.AdoNet.Util; using NHibernate.Cache; @@ -10,6 +9,7 @@ using NHibernate.Dialect; using NHibernate.Exceptions; using NHibernate.Hql; +using NHibernate.Linq; using NHibernate.Linq.Functions; using NHibernate.Linq.Visitors; using NHibernate.Transaction; @@ -137,6 +137,8 @@ public Settings BuildSettings(IDictionary properties) settings.QueryTranslatorFactory = CreateQueryTranslatorFactory(properties); + settings.LinqQueryProviderType = CreateLinqQueryProviderType(properties); + IDictionary querySubstitutions = PropertiesHelper.ToDictionary(Environment.QuerySubstitutions, " ,=;:\n\t\r\f", properties); if (log.IsInfoEnabled) @@ -365,6 +367,21 @@ private static IQueryTranslatorFactory CreateQueryTranslatorFactory(IDictionary< } } + private static System.Type CreateLinqQueryProviderType(IDictionary properties) + { + string className = PropertiesHelper.GetString( + Environment.QueryLinqProvider, properties, typeof(DefaultQueryProvider).FullName); + log.Info("Query provider: " + className); + try + { + return System.Type.GetType(className, true); + } + catch (Exception cnfe) + { + throw new HibernateException("could not find query provider class: " + className, cnfe); + } + } + private static ITransactionFactory CreateTransactionFactory(IDictionary properties) { string className = PropertiesHelper.GetString( diff --git a/src/NHibernate/Linq/DefaultQueryProvider.cs b/src/NHibernate/Linq/DefaultQueryProvider.cs index a2a01ea8b48..432fee40f6a 100644 --- a/src/NHibernate/Linq/DefaultQueryProvider.cs +++ b/src/NHibernate/Linq/DefaultQueryProvider.cs @@ -18,7 +18,7 @@ public interface INhQueryProvider : IQueryProvider public class DefaultQueryProvider : INhQueryProvider { - private static readonly MethodInfo CreateQueryMethodDefinition = ReflectionHelper.GetMethodDefinition((DefaultQueryProvider p) => p.CreateQuery(null)); + private static readonly MethodInfo CreateQueryMethodDefinition = ReflectionHelper.GetMethodDefinition((INhQueryProvider p) => p.CreateQuery(null)); private readonly WeakReference _session; @@ -66,7 +66,7 @@ public virtual object ExecuteFuture(Expression expression) return ExecuteFutureQuery(nhLinqExpression, query, nhQuery); } - protected NhLinqExpression PrepareQuery(Expression expression, out IQuery query, out NhLinqExpression nhQuery) + protected virtual NhLinqExpression PrepareQuery(Expression expression, out IQuery query, out NhLinqExpression nhQuery) { var nhLinqExpression = new NhLinqExpression(expression, Session.Factory); @@ -161,7 +161,7 @@ private static void SetParameters(IQuery query, IDictionary> parameters) + public virtual void SetResultTransformerAndAdditionalCriteria(IQuery query, NhLinqExpression nhExpression, IDictionary> parameters) { query.SetResultTransformer(nhExpression.ExpressionToHqlTranslationResults.ResultTransformer); diff --git a/src/NHibernate/Linq/NhQueryable.cs b/src/NHibernate/Linq/NhQueryable.cs index 7060d4414aa..31ca1b97b39 100644 --- a/src/NHibernate/Linq/NhQueryable.cs +++ b/src/NHibernate/Linq/NhQueryable.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using System.Linq.Expressions; using NHibernate.Engine; @@ -12,7 +13,7 @@ public class NhQueryable : QueryableBase { // This constructor is called by our users, create a new IQueryExecutor. public NhQueryable(ISessionImplementor session) - : base(new DefaultQueryProvider(session)) + : base(QueryProviderFactory.CreateQueryProvider(session)) { } diff --git a/src/NHibernate/Linq/QueryProviderFactory.cs b/src/NHibernate/Linq/QueryProviderFactory.cs new file mode 100644 index 00000000000..52c4b8119c7 --- /dev/null +++ b/src/NHibernate/Linq/QueryProviderFactory.cs @@ -0,0 +1,25 @@ +using System; +using NHibernate.Engine; + +namespace NHibernate.Linq +{ + static class QueryProviderFactory + { + /// + /// Builds a new query provider. + /// + /// A session. + /// The new query provider instance. + public static INhQueryProvider CreateQueryProvider(ISessionImplementor session) + { + if (session.Factory.Settings.LinqQueryProviderType == null) + { + return new DefaultQueryProvider(session); + } + else + { + return Activator.CreateInstance(session.Factory.Settings.LinqQueryProviderType, session) as INhQueryProvider; + } + } + } +} diff --git a/src/NHibernate/NHibernate.csproj b/src/NHibernate/NHibernate.csproj index 158da857eda..6aa2739ef1a 100644 --- a/src/NHibernate/NHibernate.csproj +++ b/src/NHibernate/NHibernate.csproj @@ -299,6 +299,7 @@ + diff --git a/src/NHibernate/nhibernate-configuration.xsd b/src/NHibernate/nhibernate-configuration.xsd index db96cf37c31..d1942c3e3a4 100644 --- a/src/NHibernate/nhibernate-configuration.xsd +++ b/src/NHibernate/nhibernate-configuration.xsd @@ -93,6 +93,7 @@ +