Skip to content

Commit c1db2d1

Browse files
committed
Merge branch 'fredericDelaporte-NH-3961'
2 parents e5cf3e4 + aba2943 commit c1db2d1

File tree

9 files changed

+426
-12
lines changed

9 files changed

+426
-12
lines changed

doc/reference/modules/query_linq.xml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
<para>
99
The Linq provider works as an extension of the <literal>ISession</literal>. It is defined in the
1010
<literal>NHibernate.Linq</literal> namespace, so this namespace has to be imported for using the
11-
Linq provider. Of course, the LINQ namespace is still needed too.
11+
Linq provider. Of course, the Linq namespace is still needed too.
1212
</para>
1313
<programlisting><![CDATA[using System.Linq;
1414
using NHibernate.Linq;]]></programlisting>
1515
<para>
1616
Note: NHibernate has another querying API which uses lambda, <link linkend="queryqueryover">QueryOver</link>.
17-
It should not be confused with a LINQ provider.
17+
It should not be confused with a Linq provider.
1818
</para>
1919

2020
<sect1 id="querylinq-querystructure">
@@ -545,9 +545,10 @@ IList<Cat> cats =
545545
}
546546
}]]></programlisting>
547547
<para>
548-
It is required that at least one of the parameters of the method call has its value originating
549-
from an entity. Otherwise, the Linq provider will try to evaluate the method call with .Net
550-
runtime.
548+
The method call will always be translated to SQL if at least one of the parameters of the
549+
method call has its value originating from an entity. Otherwise, the Linq provider will try to
550+
evaluate the method call with .Net runtime instead. Since NHibernate 5.0, if this runtime
551+
evaluation fails (throws an exception), then the method call will be translated to SQL too.
551552
</para>
552553
</sect2>
553554

@@ -565,7 +566,7 @@ IList<Cat> cats =
565566
<para>&nbsp;</para>
566567
<para>
567568
As an example, here is how to add support for an <literal>AsNullable</literal> method which
568-
would allow to call aggregates which lay yield <literal>null</literal> without to explicitly
569+
would allow to call aggregates which may yield <literal>null</literal> without to explicitly
569570
cast to the nullable type of the aggregate.
570571
</para>
571572
<programlisting><![CDATA[public static class NullableExtensions
@@ -579,7 +580,7 @@ IList<Cat> cats =
579580
}
580581
}]]></programlisting>
581582
<para>
582-
Adding support in Linq to NHibernate for this custom method requires a generator. For this
583+
Adding support in Linq to NHibernate for a custom method requires a generator. For this
583584
<literal>AsNullable</literal> method, we need a method generator, declaring statically its
584585
supported method.
585586
</para>
@@ -612,8 +613,8 @@ IList<Cat> cats =
612613
</para>
613614
<para>
614615
For adding <literal>AsNullableGenerator</literal> in Linq to NHibernate provider, a new
615-
generators registry should be used. Derive from the default one and merge it. (Static
616-
declaration of method support case.)
616+
generators registry should be used. Derive from the default one and merge it. (Here we
617+
have a static declaration of method support case.)
617618
</para>
618619
<programlisting><![CDATA[public class ExtendedLinqToHqlGeneratorsRegistry :
619620
DefaultLinqToHqlGeneratorsRegistry
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH3386
4+
{
5+
class Entity
6+
{
7+
public virtual Guid Id { get; set; }
8+
public virtual string Name { get; set; }
9+
}
10+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System.Linq;
2+
using NHibernate.Linq;
3+
using NUnit.Framework;
4+
using System;
5+
using NHibernate.SqlCommand;
6+
7+
namespace NHibernate.Test.NHSpecificTest.NH3386
8+
{
9+
[TestFixture]
10+
public class Fixture : BugTestCase
11+
{
12+
protected override bool AppliesTo(Dialect.Dialect dialect)
13+
{
14+
return dialect is Dialect.MsSql2000Dialect;
15+
}
16+
17+
protected override void OnSetUp()
18+
{
19+
using (ISession session = OpenSession())
20+
using (ITransaction transaction = session.BeginTransaction())
21+
{
22+
var e1 = new Entity {Name = "Bob"};
23+
session.Save(e1);
24+
25+
var e2 = new Entity {Name = "Sally"};
26+
session.Save(e2);
27+
28+
session.Flush();
29+
transaction.Commit();
30+
}
31+
}
32+
33+
protected override void OnTearDown()
34+
{
35+
using (ISession session = OpenSession())
36+
using (ITransaction transaction = session.BeginTransaction())
37+
{
38+
session.Delete("from System.Object");
39+
40+
session.Flush();
41+
transaction.Commit();
42+
}
43+
}
44+
45+
[Test]
46+
public void ShouldSupportNonRuntimeExtensionWithoutEntityReference()
47+
{
48+
var sqlInterceptor = new SqlInterceptor();
49+
using (ISession session = OpenSession(sqlInterceptor))
50+
using (session.BeginTransaction())
51+
{
52+
var result = session.Query<Entity>()
53+
.OrderBy(e => SqlServerFunction.NewID());
54+
55+
Assert.DoesNotThrow(() => { result.ToList(); });
56+
Assert.That(sqlInterceptor.Sql.ToString(), Does.Contain(nameof(SqlServerFunction.NewID)).IgnoreCase);
57+
}
58+
}
59+
}
60+
61+
public static class SqlServerFunction
62+
{
63+
[LinqExtensionMethod]
64+
public static Guid NewID()
65+
{
66+
throw new InvalidOperationException("To be translated to SQL only");
67+
}
68+
}
69+
70+
public class SqlInterceptor: EmptyInterceptor
71+
{
72+
public SqlString Sql { get; private set; }
73+
74+
public override SqlString OnPrepareStatement(SqlString sql)
75+
{
76+
Sql = sql;
77+
return base.OnPrepareStatement(sql);
78+
}
79+
}
80+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" namespace="NHibernate.Test.NHSpecificTest.NH3386">
3+
4+
<class name="Entity">
5+
<id name="Id" generator="guid.comb" />
6+
<property name="Name" />
7+
</class>
8+
9+
</hibernate-mapping>

0 commit comments

Comments
 (0)