Skip to content

NH-2401 - A method to specify IType of LINQ parameter #421

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

Merged
merged 1 commit into from
Apr 29, 2015
Merged
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
27 changes: 27 additions & 0 deletions src/NHibernate.Test/Linq/ParameterisedQueries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq.Expressions;
using NHibernate.Linq;
using NHibernate.DomainModel.Northwind.Entities;
using NHibernate.Type;
using NUnit.Framework;

namespace NHibernate.Test.Linq
Expand Down Expand Up @@ -55,6 +56,32 @@ public void Expressions_Differing_Only_By_Constants_Return_The_Same_Key()
}
}

[Test]
public void CanSpecifyParameterTypeInfo()
{
using (var s = OpenSession())
{
var db = new Northwind(s);

Expression<Func<IEnumerable<Customer>>> london =
() => from c in db.Customers where c.Address.City == "London".MappedAs(NHibernateUtil.StringClob) select c;

Expression<Func<IEnumerable<Customer>>> newYork =
() => from c in db.Customers where c.Address.City == "New York".MappedAs(NHibernateUtil.AnsiString) select c;

var nhLondon = new NhLinqExpression(london.Body, sessions);
var nhNewYork = new NhLinqExpression(newYork.Body, sessions);

var londonParameter = nhLondon.ParameterValuesByName.Single().Value;
Assert.That(londonParameter.Item1, Is.EqualTo("London"));
Assert.That(londonParameter.Item2, Is.EqualTo(NHibernateUtil.StringClob));

var newYorkParameter = nhNewYork.ParameterValuesByName.Single().Value;
Assert.That(newYorkParameter.Item1, Is.EqualTo("New York"));
Assert.That(newYorkParameter.Item2, Is.EqualTo(NHibernateUtil.AnsiString));
}
}

[Test]
public void Different_Where_Clauses_Return_Different_Keys()
{
Expand Down
7 changes: 6 additions & 1 deletion src/NHibernate/Linq/LinqExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Linq.Expressions;
using NHibernate.Impl;
using NHibernate.Type;
using Remotion.Linq;
using Remotion.Linq.Parsing.ExpressionTreeVisitors;

Expand Down Expand Up @@ -47,7 +48,6 @@ public static IQueryable<T> CacheRegion<T>(this IQueryable<T> query, string regi
return new NhQueryable<T>(query.Provider, callExpression);
}


public static IQueryable<T> Timeout<T>(this IQueryable<T> query, int timeout)
{
var method = ReflectionHelper.GetMethodDefinition(() => Timeout<object>(null, 0)).MakeGenericMethod(typeof(T));
Expand Down Expand Up @@ -84,6 +84,11 @@ public static IFutureValue<T> ToFutureValue<T>(this IQueryable<T> query)
return (IFutureValue<T>) future;
}

public static T MappedAs<T>(this T parameter, IType type)
{
throw new InvalidOperationException("The method should be used inside Linq to indicate a type of a parameter");
}

public static IFutureValue<TResult> ToFutureValue<T, TResult>(this IQueryable<T> query, Expression<Func<IQueryable<T>, TResult>> selector)
{
var nhQueryable = query as QueryableBase<T>;
Expand Down
12 changes: 10 additions & 2 deletions src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using NHibernate.Engine;
using NHibernate.Param;
using NHibernate.Type;
using Remotion.Linq.Parsing;
using Remotion.Linq.Utilities;

namespace NHibernate.Linq.Visitors
{
Expand Down Expand Up @@ -44,6 +42,16 @@ public static IDictionary<ConstantExpression, NamedParameter> Visit(Expression e

protected override Expression VisitMethodCallExpression(MethodCallExpression expression)
{
if (expression.Method.Name == "MappedAs" && expression.Method.DeclaringType == typeof(LinqExtensionMethods))
{
var parameter = (ConstantExpression) VisitExpression(expression.Arguments[0]);
var type = (ConstantExpression) expression.Arguments[1];

_parameters[parameter].Type = (IType) type.Value;

return parameter;
}

var method = expression.Method.IsGenericMethod
? expression.Method.GetGenericMethodDefinition()
: expression.Method;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.Linq.Expressions;
using Remotion.Linq.Clauses.Expressions;
using Remotion.Linq.Parsing;
using Remotion.Linq.Parsing.ExpressionTreeVisitors;

namespace NHibernate.Linq.Visitors
{
internal class NhPartialEvaluatingExpressionTreeVisitor : ExpressionTreeVisitor
internal class NhPartialEvaluatingExpressionTreeVisitor : ExpressionTreeVisitor, IPartialEvaluationExceptionExpressionVisitor
{
protected override Expression VisitConstantExpression(ConstantExpression expression)
{
Expand All @@ -22,5 +23,10 @@ public static Expression EvaluateIndependentSubtrees(Expression expression)
var evaluatedExpression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees(expression);
return new NhPartialEvaluatingExpressionTreeVisitor().VisitExpression(evaluatedExpression);
}

public Expression VisitPartialEvaluationExceptionExpression(PartialEvaluationExceptionExpression expression)
{
return VisitExpression(expression.Reduce());
}
}
}