Skip to content

Commit

Permalink
Merge branch 'pr/n639_sdanyliv'
Browse files Browse the repository at this point in the history
  • Loading branch information
igor-tkachev committed Apr 21, 2017
2 parents e75c6b2 + 4aae278 commit de8f06a
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Source/Common/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ public static class Linq
/// </example>
/// </summary>
public static bool CheckNullForNotEquals = true;

/// <summary>
/// Prevents to use constructions like q.GroupBy(_ => _.SomeValue) which leads to unexpected behaviour.
/// </summary>
public static bool GuardGrouping = false;
}

public static class LinqService
Expand Down
14 changes: 14 additions & 0 deletions Source/Linq/Builder/GroupByBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,20 @@ class GroupByHelper<TKey,TElement,TSource> : IGroupByHelper
{
public Expression GetGrouping(GroupByContext context)
{
if (Configuration.Linq.GuardGrouping)
{
if (context._element.Lambda.Parameters.Count == 1 &&
context._element.Body == context._element.Lambda.Parameters[0])
{
var ex = new LinqToDBException(
"You should explicitly specify selected fields for server-side GroupBy() call or add AsEnumerable() call before GroupBy() to perform client-side grouping.\n" +
"Set Configuration.Linq.GuardGrouping = false to disable this check."
);
ex.HelpLink = "https://github.com/linq2db/linq2db/issues/365";
throw ex;
}
}

var parameters = context.Builder.CurrentSqlParameters
.Select((p,i) => new { p, i })
.ToDictionary(_ => _.p.Expression, _ => _.i);
Expand Down
48 changes: 48 additions & 0 deletions Tests/Linq/Linq/GroupByTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1824,5 +1824,53 @@ select gc.Key
);
}
}

[Test, DataContextSource]
public void GroupByGuard(string context)
{
using(new AllowMultipleQuery())
using(new GuardGrouping())
using (var db = GetDataContext(context))
{
// group on client
var dictionary1 = db.Person
.AsEnumerable()
.GroupBy(_ => _.Gender)
.ToDictionary(_ => _.Key, _ => _.ToList());

Assert.AreEqual(2, dictionary1.Count);
Assert.AreEqual(2, dictionary1.First().Value.Count);

var list =
(
from p in db.Person
group p by p.Gender into gr
select new { gr.Key, Count = gr.Count() }
)
.ToDictionary(_ => _.Key);

Assert.Throws<LinqToDBException>(() =>
{
// group on server
db.Person
.GroupBy(_ => _.Gender)
.ToDictionary(_ => _.Key, _ => _.ToList());
});

Assert.Throws<LinqToDBException>(() =>
{
db.Person
.GroupBy(_ => _)
.ToDictionary(_ => _.Key, _ => _.ToList());
});

Assert.Throws<LinqToDBException>(() =>
{
db.Person
.GroupBy(_ => _)
.ToList();
});
}
}
}
}
13 changes: 13 additions & 0 deletions Tests/Linq/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,19 @@ public void Dispose()
}
}

public class GuardGrouping : IDisposable
{
public GuardGrouping()
{
Configuration.Linq.GuardGrouping = true;
}

public void Dispose()
{
Configuration.Linq.GuardGrouping = false;
}
}

public class WithoutJoinOptimization : IDisposable
{
public WithoutJoinOptimization()
Expand Down

0 comments on commit de8f06a

Please sign in to comment.