From 34e77627e984c3d727aaee3cd3fd240fca5725b4 Mon Sep 17 00:00:00 2001 From: Onur Gumus Date: Sun, 17 Aug 2014 15:49:27 +0300 Subject: [PATCH 1/3] fixes NH-2285 --- src/NHibernate.Test/Linq/QueryLock.cs | 47 +++++++++++++++++++ .../ResultOperatorProcessors/ProcessLock.cs | 16 +++++++ 2 files changed, 63 insertions(+) create mode 100644 src/NHibernate.Test/Linq/QueryLock.cs create mode 100644 src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessLock.cs diff --git a/src/NHibernate.Test/Linq/QueryLock.cs b/src/NHibernate.Test/Linq/QueryLock.cs new file mode 100644 index 00000000000..d2bc49db469 --- /dev/null +++ b/src/NHibernate.Test/Linq/QueryLock.cs @@ -0,0 +1,47 @@ +using System.Linq; +using NHibernate.AdoNet; +using NHibernate.Cfg; +using NHibernate.Engine; +using NHibernate.Linq; +using NUnit.Framework; + +namespace NHibernate.Test.Linq +{ + public class QueryLock : LinqTestCase + { + + [Test] + public void CanSetLockLinqQueries() + { + var result = (from e in db.Customers + where e.CompanyName == "Corp" + select e).SetLockMode(LockMode.Upgrade).ToList(); + + } + + + [Test] + public void CanSetLockOnLinqPagingQuery() + { + var result = (from e in db.Customers + where e.CompanyName == "Corp" + select e).Skip(5).Take(5).SetLockMode(LockMode.Upgrade).ToList(); + } + + + [Test] + public void CanLockBeforeSkipOnLinqOrderedPageQuery() + { + var result = (from e in db.Customers + orderby e.CompanyName + select e) + .SetLockMode(LockMode.Upgrade).Skip(5).Take(5).ToList(); + + + } + + + } + +} + diff --git a/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessLock.cs b/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessLock.cs new file mode 100644 index 00000000000..514b7bebcc5 --- /dev/null +++ b/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessLock.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NHibernate.Linq.Visitors.ResultOperatorProcessors +{ + internal class ProcessLock : IResultOperatorProcessor + { + public void Process(LockResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) + { + tree.AddAdditionalCriteria((q, p) => q.SetLockMode(queryModelVisitor.Model.MainFromClause.ItemName, (LockMode)resultOperator.LockMode.Value)); + } + } +} + From dd6e89bae73c3cb688791796ed0837075934460e Mon Sep 17 00:00:00 2001 From: Onur Gumus Date: Sun, 17 Aug 2014 15:50:01 +0300 Subject: [PATCH 2/3] changed files --- .../GroupBy/AggregatingGroupByRewriter.cs | 1 + src/NHibernate/Linq/LinqExtensionMethods.cs | 9 +++ src/NHibernate/Linq/NhRelinqQueryParser.cs | 62 +++++++++++++++++++ .../Linq/ReWriters/ResultOperatorRewriter.cs | 1 + .../Linq/Visitors/QueryModelVisitor.cs | 1 + 5 files changed, 74 insertions(+) diff --git a/src/NHibernate/Linq/GroupBy/AggregatingGroupByRewriter.cs b/src/NHibernate/Linq/GroupBy/AggregatingGroupByRewriter.cs index e7b3acd7654..6c429d29adf 100644 --- a/src/NHibernate/Linq/GroupBy/AggregatingGroupByRewriter.cs +++ b/src/NHibernate/Linq/GroupBy/AggregatingGroupByRewriter.cs @@ -38,6 +38,7 @@ public static class AggregatingGroupByRewriter typeof (AnyResultOperator), typeof (AllResultOperator), typeof (TimeoutResultOperator), + typeof (LockResultOperator), }; public static void ReWrite(QueryModel queryModel) diff --git a/src/NHibernate/Linq/LinqExtensionMethods.cs b/src/NHibernate/Linq/LinqExtensionMethods.cs index c8b9acb2c0b..a49147fc2bb 100755 --- a/src/NHibernate/Linq/LinqExtensionMethods.cs +++ b/src/NHibernate/Linq/LinqExtensionMethods.cs @@ -28,6 +28,15 @@ public static IQueryable Cacheable(this IQueryable query) return new NhQueryable(query.Provider, callExpression); } + public static IQueryable SetLockMode(this IQueryable query, LockMode lockMode) + { + var method = ReflectionHelper.GetMethodDefinition(() => SetLockMode(null, LockMode.Read)).MakeGenericMethod(typeof(T)); + + var callExpression = Expression.Call(method, query.Expression, Expression.Constant(lockMode)); + + return new NhQueryable(query.Provider, callExpression); + } + public static IQueryable CacheMode(this IQueryable query, CacheMode cacheMode) { diff --git a/src/NHibernate/Linq/NhRelinqQueryParser.cs b/src/NHibernate/Linq/NhRelinqQueryParser.cs index 4ef1f85ac29..f6bcf864cb3 100644 --- a/src/NHibernate/Linq/NhRelinqQueryParser.cs +++ b/src/NHibernate/Linq/NhRelinqQueryParser.cs @@ -77,6 +77,13 @@ public NHibernateNodeTypeProvider() ReflectionHelper.GetMethodDefinition(() => LinqExtensionMethods.Timeout(null, 0)), }, typeof (TimeoutExpressionNode) ); + methodInfoRegistry.Register( + new[] + { + ReflectionHelper.GetMethodDefinition(() => LinqExtensionMethods.SetLockMode(null, LockMode.Read)), + }, typeof(LockExpressionNode) + ); + var nodeTypeProvider = ExpressionTreeParser.CreateDefaultNodeTypeProvider(); nodeTypeProvider.InnerProviders.Add(methodInfoRegistry); @@ -137,6 +144,30 @@ protected override ResultOperatorBase CreateResultOperator(ClauseGenerationConte } } + internal class LockExpressionNode : ResultOperatorExpressionNodeBase + { + private readonly MethodCallExpressionParseInfo _parseInfo; + private readonly ConstantExpression _lockMode; + + public LockExpressionNode(MethodCallExpressionParseInfo parseInfo, ConstantExpression lockMode) + : base(parseInfo, null, null) + { + _parseInfo = parseInfo; + _lockMode = lockMode; + } + + public override Expression Resolve(ParameterExpression inputParameter, Expression expressionToBeResolved, ClauseGenerationContext clauseGenerationContext) + { + return Source.Resolve(inputParameter, expressionToBeResolved, clauseGenerationContext); + } + + protected override ResultOperatorBase CreateResultOperator(ClauseGenerationContext clauseGenerationContext) + { + return new LockResultOperator(_parseInfo, _lockMode); + } + } + + public class CacheableResultOperator : ResultOperatorBase { public MethodCallExpressionParseInfo ParseInfo { get; private set; } @@ -222,4 +253,35 @@ public override void TransformExpressions(Func transform { } } + internal class LockResultOperator : ResultOperatorBase + { + public MethodCallExpressionParseInfo ParseInfo { get; private set; } + public ConstantExpression LockMode { get; private set; } + + public LockResultOperator(MethodCallExpressionParseInfo parseInfo, ConstantExpression lockMode) + { + ParseInfo = parseInfo; + LockMode = lockMode; + } + + public override IStreamedData ExecuteInMemory(IStreamedData input) + { + throw new NotImplementedException(); + } + + public override IStreamedDataInfo GetOutputDataInfo(IStreamedDataInfo inputInfo) + { + return inputInfo; + } + + public override ResultOperatorBase Clone(CloneContext cloneContext) + { + throw new NotImplementedException(); + } + + public override void TransformExpressions(Func transformation) + { + } + } + } \ No newline at end of file diff --git a/src/NHibernate/Linq/ReWriters/ResultOperatorRewriter.cs b/src/NHibernate/Linq/ReWriters/ResultOperatorRewriter.cs index 553f9ff27e1..ec4ea39d1d6 100644 --- a/src/NHibernate/Linq/ReWriters/ResultOperatorRewriter.cs +++ b/src/NHibernate/Linq/ReWriters/ResultOperatorRewriter.cs @@ -67,6 +67,7 @@ private class ResultOperatorExpressionRewriter : ExpressionTreeVisitor typeof(OfTypeResultOperator), typeof(CacheableResultOperator), typeof(TimeoutResultOperator), + typeof (LockResultOperator), typeof(CastResultOperator), // see ProcessCast class }; diff --git a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs index 0257395aa63..a0338226963 100644 --- a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs +++ b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs @@ -106,6 +106,7 @@ static QueryModelVisitor() ResultOperatorMap.Add(); ResultOperatorMap.Add(); ResultOperatorMap.Add(); + ResultOperatorMap.Add(); ResultOperatorMap.Add(); ResultOperatorMap.Add(); } From fc7b6d5e5a83fc0c0a16fe08b2796a48b912642d Mon Sep 17 00:00:00 2001 From: Onur Gumus Date: Sun, 17 Aug 2014 15:56:04 +0300 Subject: [PATCH 3/3] .proj files --- src/NHibernate.Test/NHibernate.Test.csproj | 1 + src/NHibernate/NHibernate.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/src/NHibernate.Test/NHibernate.Test.csproj b/src/NHibernate.Test/NHibernate.Test.csproj index eca05f3f59c..5aa048bc42b 100644 --- a/src/NHibernate.Test/NHibernate.Test.csproj +++ b/src/NHibernate.Test/NHibernate.Test.csproj @@ -519,6 +519,7 @@ + diff --git a/src/NHibernate/NHibernate.csproj b/src/NHibernate/NHibernate.csproj index cadb95fddf4..d958d627674 100644 --- a/src/NHibernate/NHibernate.csproj +++ b/src/NHibernate/NHibernate.csproj @@ -312,6 +312,7 @@ +