Skip to content

NH-3944 - Relinq v2 migration #599

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions doc/reference/modules/query_linq.xml
Original file line number Diff line number Diff line change
Expand Up @@ -539,16 +539,18 @@ IList<Cat> cats =
<programlisting><![CDATA[public static class CustomLinqExtensions
{
[LinqExtensionMethod("dbo.aCustomFunction")]
[DBOnly]
public static string ACustomFunction(this string input, string otherInput)
{
throw new NotImplementedException();
}
}]]></programlisting>
<para>
The method call will always be translated to SQL if at least one of the parameters of the
method call has its value originating from an entity. Otherwise, the Linq provider will try to
evaluate the method call with .Net runtime instead. Since NHibernate 5.0, if this runtime
evaluation fails (throws an exception), then the method call will be translated to SQL too.
By default, the Linq provider will try to evaluate the method call with .Net runtime
whenever possible, instead of translating it to SQL. It will not do it if at least one
of the parameters of the method call has its value originating from an entity, or if
the method is marked with the <literal>DBOnly</literal> attribute (available since
NHibernate 5.0).
</para>
</sect2>

Expand Down Expand Up @@ -656,6 +658,13 @@ cfg.LinqToHqlGeneratorsRegistry<ExtendedLinqToHqlGeneratorsRegistry>();
<para>
(Of course, the same result could be obtained with <literal>(DateTime?)(c.BirthDate)</literal>.)
</para>
<para>
By default, the Linq provider will try to evaluate the method call with .Net runtime
whenever possible, instead of translating it to SQL. It will not do it if at least one
of the parameters of the method call has its value originating from an entity, or if
the method is marked with the <literal>DBOnly</literal> attribute (available since
NHibernate 5.0).
</para>
</sect2>
</sect1>
</chapter>
1 change: 1 addition & 0 deletions src/NHibernate.DomainModel/NHibernate.DomainModel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
Expand Down
11 changes: 11 additions & 0 deletions src/NHibernate.DomainModel/app.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Remotion.Linq" publicKeyToken="fee00910d6e5f53b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
14 changes: 9 additions & 5 deletions src/NHibernate.Test/App.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>

<configSections>
Expand All @@ -15,6 +15,10 @@
<!-- Required by ReflectHelperFixture.TypeFoundInNotLoadedAssembly test -->
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" applies-to="v2.0.50727">
<qualifyAssembly partialName="System.Web" fullName="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<dependentAssembly>
<assemblyIdentity name="Remotion.Linq" publicKeyToken="fee00910d6e5f53b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

Expand Down Expand Up @@ -66,7 +70,7 @@
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<appender name="rollingFile" type="log4net.Appender.RollingFileAppender, log4net" >
<appender name="rollingFile" type="log4net.Appender.RollingFileAppender, log4net">
<param name="File" value="log.txt" />
<param name="AppendToFile" value="false" />
<param name="RollingStyle" value="Date" />
Expand Down Expand Up @@ -98,12 +102,12 @@

</log4net>

<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/></startup>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /></startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="nunit.framework" publicKeyToken="96d09a1eb7f44a77" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.6.1.12217" newVersion="2.6.1.12217"/>
<assemblyIdentity name="nunit.framework" publicKeyToken="96d09a1eb7f44a77" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.1.12217" newVersion="2.6.1.12217" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Expand Down
18 changes: 18 additions & 0 deletions src/NHibernate.Test/Linq/ByMethod/GroupByHavingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,23 @@ public void SingleKeyGroupAndCountWithHavingClause()
var hornRow = orderCounts.Single(row => row.CompanyName == "Around the Horn");
Assert.That(hornRow.OrderCount, Is.EqualTo(13));
}

[Test, Explicit("Demonstrate an unsupported case for PagingRewriter")]
public void SingleKeyGroupAndCountWithHavingClausePagingAndOuterWhere()
{
var orderCounts = db.Orders
.GroupBy(o => o.Customer.CompanyName)
.Where(g => g.Count() > 10)
.Select(g => new { CompanyName = g.Key, OrderCount = g.Count() })
.OrderBy(oc => oc.CompanyName)
.Skip(5)
.Take(10)
.Where(oc => oc.CompanyName.Contains("F"))
.ToList();

Assert.That(orderCounts, Has.Count.EqualTo(3));
var frankRow = orderCounts.Single(row => row.CompanyName == "Frankenversand");
Assert.That(frankRow.OrderCount, Is.EqualTo(15));
}
}
}
12 changes: 5 additions & 7 deletions src/NHibernate.Test/Linq/CustomQueryModelRewriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ public class CustomVisitor : QueryModelVisitorBase
{
public override void VisitWhereClause(WhereClause whereClause, QueryModel queryModel, int index)
{
whereClause.TransformExpressions(new Visitor().VisitExpression);
whereClause.TransformExpressions(new Visitor().Visit);
}

private class Visitor : ExpressionTreeVisitor
private class Visitor : RelinqExpressionVisitor
{
protected override Expression VisitBinaryExpression(BinaryExpression expression)
protected override Expression VisitBinary(BinaryExpression expression)
{
if (
expression.NodeType == ExpressionType.Equal ||
Expand All @@ -68,9 +68,7 @@ protected override Expression VisitBinaryExpression(BinaryExpression expression)
reverse = true;
}

var constant = left as ConstantExpression;

if (constant != null && constant.Value == null)
if (left is ConstantExpression constant && constant.Value == null)
{
left = Expression.Constant("Thomas Hardy");

Expand All @@ -82,7 +80,7 @@ protected override Expression VisitBinaryExpression(BinaryExpression expression)
}
}

return base.VisitBinaryExpression(expression);
return base.VisitBinary(expression);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3386/Fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public void ShouldSupportNonRuntimeExtensionWithoutEntityReference()
public static class SqlServerFunction
{
[LinqExtensionMethod]
[DBOnly]
public static Guid NewID()
{
throw new InvalidOperationException("To be translated to SQL only");
Expand Down
10 changes: 7 additions & 3 deletions src/NHibernate.Test/NHibernate.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,14 @@
<HintPath>..\packages\NUnit.3.6.0\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Remotion.Linq, Version=2.1.0.0, Culture=neutral, PublicKeyToken=fee00910d6e5f53b, processorArchitecture=MSIL">
<HintPath>..\packages\Remotion.Linq.2.1.1\lib\net45\Remotion.Linq.dll</HintPath>
</Reference>
<Reference Include="Remotion.Linq.EagerFetching, Version=2.0.0.0, Culture=neutral, PublicKeyToken=fee00910d6e5f53b, processorArchitecture=MSIL">
<HintPath>..\packages\Remotion.Linq.EagerFetching.2.0.1\lib\net45\Remotion.Linq.EagerFetching.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.configuration" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
Expand All @@ -100,9 +107,6 @@
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="Remotion.Linq, Version=1.15.15.0, Culture=neutral, PublicKeyToken=fee00910d6e5f53b, processorArchitecture=MSIL">
<HintPath>..\packages\Remotion.Linq.1.15.15.0\lib\portable-net45+wp80+wpa81+win\Remotion.Linq.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedAssemblyInfo.cs">
Expand Down
14 changes: 13 additions & 1 deletion src/NHibernate.Test/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
<package id="Iesi.Collections" version="4.0.1.4000" targetFramework="net461" />
<package id="log4net" version="2.0.7" targetFramework="net461" />
<package id="NUnit" version="3.6.0" targetFramework="net461" />
<package id="Remotion.Linq" version="1.15.15.0" targetFramework="net461" />
<package id="Remotion.Linq" version="2.1.1" targetFramework="net461" />
<package id="Remotion.Linq.EagerFetching" version="2.0.1" targetFramework="net461" />
<package id="System.Collections" version="4.3.0" targetFramework="net461" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net461" />
<package id="System.Linq" version="4.3.0" targetFramework="net461" />
<package id="System.Linq.Dynamic" version="1.0.7" targetFramework="net461" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net461" />
<package id="System.Linq.Queryable" version="4.3.0" targetFramework="net461" />
<package id="System.ObjectModel" version="4.3.0" targetFramework="net461" />
<package id="System.Reflection" version="4.3.0" targetFramework="net461" />
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net461" />
<package id="System.Runtime" version="4.3.0" targetFramework="net461" />
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net461" />
<package id="System.Threading" version="4.3.0" targetFramework="net461" />
</packages>
16 changes: 12 additions & 4 deletions src/NHibernate.TestDatabaseSetup/App.config
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
</configSections>

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
Expand All @@ -13,4 +12,13 @@
</property>
</session-factory>
</hibernate-configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /></startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Remotion.Linq" publicKeyToken="fee00910d6e5f53b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
19 changes: 0 additions & 19 deletions src/NHibernate/Linq/Clauses/NhHavingClause.cs

This file was deleted.

62 changes: 0 additions & 62 deletions src/NHibernate/Linq/Clauses/NhJoinClause.cs

This file was deleted.

19 changes: 0 additions & 19 deletions src/NHibernate/Linq/Clauses/NhWithClause.cs

This file was deleted.

14 changes: 14 additions & 0 deletions src/NHibernate/Linq/DBOnlyAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace NHibernate.Linq
{
/// <summary>
/// Indicates to the Linq-to-NHibernate provider a method that must not be evaluated. If supported,
/// it will always be converted to the corresponding SQL statement.
/// </summary>
public class DBOnlyAttribute: Attribute
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better name welcome. Thanks to this attribute, we no more need to swallow silently exception raised from a non evaluatable method. Now, if the method is properly marked, no exception will be raised.

{
public DBOnlyAttribute()
{ }
}
}
8 changes: 2 additions & 6 deletions src/NHibernate/Linq/DefaultQueryProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ protected virtual ISessionImplementor Session

public virtual object Execute(Expression expression)
{
IQuery query;
NhLinqExpression nhQuery;
NhLinqExpression nhLinqExpression = PrepareQuery(expression, out query, out nhQuery);
var nhLinqExpression = PrepareQuery(expression, out IQuery query, out NhLinqExpression nhQuery);

return ExecuteQuery(nhLinqExpression, query, nhQuery);
}
Expand All @@ -61,9 +59,7 @@ public virtual IQueryable<T> CreateQuery<T>(Expression expression)

public virtual object ExecuteFuture(Expression expression)
{
IQuery query;
NhLinqExpression nhQuery;
NhLinqExpression nhLinqExpression = PrepareQuery(expression, out query, out nhQuery);
var nhLinqExpression = PrepareQuery(expression, out IQuery query, out NhLinqExpression nhQuery);
return ExecuteFutureQuery(nhLinqExpression, query, nhQuery);
}

Expand Down
Loading