You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2017/07/04 11:51:33 UTC

[1/3] ignite git commit: IGNITE-5532 .NET: Split CacheLinqTest into partial classes

Repository: ignite
Updated Branches:
  refs/heads/master 15613e2af -> 84c7427a5


http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
new file mode 100644
index 0000000..c4ef11f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
@@ -0,0 +1,350 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests the empty query.
+        /// </summary>
+        [Test]
+        public void TestEmptyQuery()
+        {
+            // There are both persons and organizations in the same cache, but query should only return specific type
+            Assert.AreEqual(PersonCount, GetPersonCache().AsCacheQueryable().ToArray().Length);
+            Assert.AreEqual(RoleCount, GetRoleCache().AsCacheQueryable().ToArray().Length);
+        }
+
+        /// <summary>
+        /// Tests the single field query.
+        /// </summary>
+        [Test]
+        public void TestSingleFieldQuery()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+
+            // Multiple values
+            Assert.AreEqual(new[] { 0, 1, 2 },
+                cache.Where(x => x.Key < 3).Select(x => x.Value.Address.Zip).ToArray());
+
+            // Single value
+            Assert.AreEqual(0, cache.Where(x => x.Key < 0).Select(x => x.Value.Age).FirstOrDefault());
+            Assert.AreEqual(3, cache.Where(x => x.Key == 3).Select(x => x.Value.Age).FirstOrDefault());
+            Assert.AreEqual(3, cache.Where(x => x.Key == 3).Select(x => x.Value).Single().Age);
+            Assert.AreEqual(3, cache.Select(x => x.Key).Single(x => x == 3));
+            Assert.AreEqual(7,
+                cache.Select(x => x.Value)
+                    .Where(x => x.Age == 7)
+                    .Select(x => x.Address)
+                    .Where(x => x.Zip > 0)
+                    .Select(x => x.Zip)
+                    .Single());
+        }
+
+        /// <summary>
+        /// Tests the field projection.
+        /// </summary>
+        [Test]
+        public void TestFieldProjection()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+
+            // Project whole cache entry to anonymous class
+            Assert.AreEqual(5, cache.Where(x => x.Key == 5).Select(x => new { Foo = x }).Single().Foo.Key);
+        }
+
+        /// <summary>
+        /// Tests the multi field query.
+        /// </summary>
+        [Test]
+        public void TestMultiFieldQuery()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+
+            // Test anonymous type (ctor invoke)
+            var data = cache
+                .Select(x => new { Id = x.Key + 20, Age_ = x.Value.Age + 10, Addr = x.Value.Address })
+                .Where(x => x.Id < 25)
+                .ToArray();
+
+            Assert.AreEqual(5, data.Length);
+
+            foreach (var t in data)
+            {
+                Assert.AreEqual(t.Age_ - 10, t.Id - 20);
+                Assert.AreEqual(t.Age_ - 10, t.Addr.Zip);
+            }
+        }
+
+        /// <summary>
+        /// Tests the scalar query.
+        /// </summary>
+        [Test]
+        public void TestScalarQuery()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+
+            Assert.AreEqual(PersonCount - 1, cache.Max(x => x.Value.Age));
+            Assert.AreEqual(0, cache.Min(x => x.Value.Age));
+
+            Assert.AreEqual(21, cache.Where(x => x.Key > 5 && x.Value.Age < 9).Select(x => x.Value.Age).Sum());
+
+            Assert.AreEqual(PersonCount, cache.Count());
+            Assert.AreEqual(PersonCount, cache.Count(x => x.Key < PersonCount));
+        }
+
+        /// <summary>
+        /// Tests conditions.
+        /// </summary>
+        [Test]
+        public void TestConditions()
+        {
+            TestConditional("even", "odd");
+            TestConditional(new Address { Zip = 99999 }, new Address { Zip = 7777777 }, (a1, a2) => a1.Zip == a2.Zip);
+            TestConditional(new RoleKey(int.MaxValue, long.MinValue), new RoleKey(int.MinValue, long.MaxValue));
+            TestConditionalWithNullableStructs<int>();
+            TestConditionalWithNullableStructs<uint>();
+            TestConditionalWithNullableStructs<Guid>();
+            TestConditionalWithNullableStructs<byte>();
+            TestConditionalWithNullableStructs<sbyte>();
+            TestConditionalWithNullableStructs<short>();
+            TestConditionalWithNullableStructs<ushort>();
+            TestConditionalWithNullableStructs<bool>();
+            TestConditionalWithNullableStructs<long>();
+            TestConditionalWithNullableStructs<ulong>();
+            TestConditionalWithNullableStructs<double>();
+            TestConditionalWithNullableStructs<float>();
+            TestConditionalWithNullableStructs<decimal>();
+            TestConditionalWithNullableStructs<DateTime>(DateTime.UtcNow);
+
+            var charException = Assert.Throws<NotSupportedException>(() => TestConditionalWithNullableStructs<char>());
+            Assert.AreEqual("Type is not supported for SQL mapping: System.Char", charException.Message);
+
+            var roles = GetRoleCache().AsCacheQueryable();
+            CheckFunc(x => x.Value.Name ?? "def_name", roles);
+        }
+
+        /// <summary>
+        /// Tests the SelectMany from field collection.
+        /// </summary>
+        [Test]
+        public void TestSelectManySameTable()
+        {
+            var persons = GetPersonCache().AsCacheQueryable();
+
+            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+            var ex = Assert.Throws<NotSupportedException>(() => persons.SelectMany(x => x.Value.Name).ToArray());
+
+            Assert.IsTrue(ex.Message.StartsWith("FROM clause must be IQueryable: from Char"));
+        }
+
+        /// <summary>
+        /// Tests nulls.
+        /// </summary>
+        [Test]
+        public void TestNulls()
+        {
+            var roles = GetRoleCache().AsCacheQueryable();
+
+            var nullNameRole = roles.Single(x => x.Value.Name == null);
+            Assert.AreEqual(null, nullNameRole.Value.Name);
+
+            var nonNullNameRoles = roles.Where(x => x.Value.Name != null);
+            Assert.AreEqual(RoleCount - 1, nonNullNameRoles.Count());
+        }
+
+        /// <summary>
+        /// Tests aliases.
+        /// </summary>
+        [Test]
+        public void TestAliases()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+
+            var res = cache.Where(x => x.Key == 1)
+                .Select(x => new { X = x.Value.AliasTest, Y = x.Value.Address.AliasTest })
+                .Single();
+
+            Assert.AreEqual(new { X = -1, Y = 1 }, res);
+        }
+
+        /// <summary>
+        /// Tests the cache of primitive types.
+        /// </summary>
+        [Test]
+        public void TestPrimitiveCache()
+        {
+            // Create partitioned cache
+            var cache = Ignition.GetIgnite()
+                .GetOrCreateCache<int, string>(
+                    new CacheConfiguration("primitiveCache",
+                        new QueryEntity(typeof(int), typeof(string)))
+                    {
+                        CacheMode = CacheMode.Replicated,
+                        SqlEscapeAll = GetSqlEscapeAll()
+                    });
+
+            var qry = cache.AsCacheQueryable();
+
+            // Populate
+            const int count = 100;
+            cache.PutAll(Enumerable.Range(0, count).ToDictionary(x => x, x => x.ToString()));
+
+            // Test
+            Assert.AreEqual(count, qry.ToArray().Length);
+            Assert.AreEqual(10, qry.Where(x => x.Key < 10).ToArray().Length);
+            Assert.AreEqual(1, qry.Count(x => x.Value.Contains("99")));
+        }
+
+        /// <summary>
+        /// Tests the local query.
+        /// </summary>
+        [Test]
+        public void TestLocalQuery()
+        {
+            // Create partitioned cache
+            var cache =
+                Ignition.GetIgnite().GetOrCreateCache<int, int>(new CacheConfiguration("partCache", typeof(int))
+                {
+                    SqlEscapeAll = GetSqlEscapeAll()
+                });
+
+            // Populate
+            const int count = 100;
+            cache.PutAll(Enumerable.Range(0, count).ToDictionary(x => x, x => x));
+
+            // Non-local query returns all records
+            Assert.AreEqual(count, cache.AsCacheQueryable(false).ToArray().Length);
+
+            // Local query returns only some of the records
+            var localCount = cache.AsCacheQueryable(true).ToArray().Length;
+            Assert.Less(localCount, count);
+            Assert.Greater(localCount, 0);
+        }
+
+        /// <summary>
+        /// Tests the table name inference.
+        /// </summary>
+        [Test]
+        public void TestTableNameInference()
+        {
+            // Try with multi-type cache: explicit type is required
+            var cache = GetCacheOf<IPerson>();
+
+            Assert.Throws<CacheException>(() => cache.AsCacheQueryable());
+
+            var names = cache.AsCacheQueryable(false, "Person").Select(x => x.Value.Name).ToArray();
+
+            Assert.AreEqual(PersonCount, names.Length);
+
+            // With single-type cache, interface inference works
+            var roleCache = Ignition.GetIgnite().GetCache<object, IRole>(RoleCacheName).AsCacheQueryable();
+
+            var roleNames = roleCache.Select(x => x.Value.Name).OrderBy(x => x).ToArray();
+
+            CollectionAssert.AreEquivalent(new[] { "Role_1", "Role_2", null }, roleNames);
+
+            // Check non-queryable cache
+            var nonQueryableCache = Ignition.GetIgnite().GetOrCreateCache<Role, Person>("nonQueryable");
+
+            Assert.Throws<CacheException>(() => nonQueryableCache.AsCacheQueryable());
+        }
+
+        /// <summary>
+        /// Tests the distributed joins.
+        /// </summary>
+        [Test]
+        public void TestDistributedJoins()
+        {
+            var ignite = Ignition.GetIgnite();
+
+            // Create and populate partitioned caches
+            var personCache = ignite.CreateCache<int, Person>(new CacheConfiguration("partitioned_persons",
+                new QueryEntity(typeof(int), typeof(Person)))
+            {
+                SqlEscapeAll = GetSqlEscapeAll()
+            });
+
+            personCache.PutAll(GetSecondPersonCache().ToDictionary(x => x.Key, x => x.Value));
+
+            var roleCache = ignite.CreateCache<int, Role>(new CacheConfiguration("partitioned_roles",
+                new QueryEntity(typeof(int), typeof(Role)))
+            {
+                SqlEscapeAll = GetSqlEscapeAll()
+            });
+
+            roleCache.PutAll(GetRoleCache().ToDictionary(x => x.Key.Foo, x => x.Value));
+
+            // Test non-distributed join: returns partial results
+            var persons = personCache.AsCacheQueryable();
+            var roles = roleCache.AsCacheQueryable();
+
+            var res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
+                .ToArray();
+
+            Assert.AreEqual(res.Length, RoleCount);
+
+            // Test distributed join: returns complete results
+            persons = personCache.AsCacheQueryable(new QueryOptions { EnableDistributedJoins = true });
+            roles = roleCache.AsCacheQueryable(new QueryOptions { EnableDistributedJoins = true });
+
+            res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
+                .ToArray();
+
+            Assert.AreEqual(RoleCount, res.Length);
+        }
+
+        /// <summary>
+        /// Tests the query timeout.
+        /// </summary>
+        [Test]
+        public void TestTimeout()
+        {
+            var persons = GetPersonCache().AsCacheQueryable(new QueryOptions
+            {
+                Timeout = TimeSpan.FromMilliseconds(1),
+                EnableDistributedJoins = true
+            });
+
+            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+            var ex = Assert.Throws<CacheException>(() =>
+                persons.SelectMany(p => GetRoleCache().AsCacheQueryable()).ToArray());
+
+            Assert.IsTrue(ex.ToString().Contains("QueryCancelledException: The query was cancelled while executing."));
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Numerics.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Numerics.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Numerics.cs
new file mode 100644
index 0000000..3f973aa
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Numerics.cs
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests numerics.
+        /// </summary>
+        [Test]
+        public void TestNumerics()
+        {
+            var cache = Ignition.GetIgnite()
+                .GetOrCreateCache<int, Numerics>(new CacheConfiguration("numerics", typeof(Numerics))
+                {
+                    SqlEscapeAll = GetSqlEscapeAll()
+                });
+
+            for (var i = 0; i < 100; i++)
+                cache[i] = new Numerics(((double)i - 50) / 3);
+
+            var query = cache.AsCacheQueryable().Select(x => x.Value);
+
+            var bytes = query.Select(x => x.Byte);
+            var sbytes = query.Select(x => x.Sbyte);
+            var shorts = query.Select(x => x.Short);
+            var ushorts = query.Select(x => x.Ushort);
+            var ints = query.Select(x => x.Int);
+            var uints = query.Select(x => x.Uint);
+            var longs = query.Select(x => x.Long);
+            var ulongs = query.Select(x => x.Ulong);
+            var doubles = query.Select(x => x.Double);
+            var decimals = query.Select(x => x.Decimal);
+            var floats = query.Select(x => x.Float);
+
+            CheckFunc(x => Math.Abs(x), doubles);
+            CheckFunc(x => Math.Abs((sbyte)x), bytes);
+            CheckFunc(x => Math.Abs(x), sbytes);
+            CheckFunc(x => Math.Abs(x), shorts);
+            CheckFunc(x => Math.Abs((short)x), ushorts);
+            CheckFunc(x => Math.Abs(x), ints);
+            CheckFunc(x => Math.Abs((int)x), uints);
+            CheckFunc(x => Math.Abs(x), longs);
+            CheckFunc(x => Math.Abs((long)x), ulongs);
+            CheckFunc(x => Math.Abs(x), decimals);
+            CheckFunc(x => Math.Abs(x), floats);
+
+            CheckFunc(x => Math.Acos(x), doubles);
+            CheckFunc(x => Math.Asin(x), doubles);
+            CheckFunc(x => Math.Atan(x), doubles);
+            CheckFunc(x => Math.Atan2(x, 0.5), doubles);
+
+            CheckFunc(x => Math.Ceiling(x), doubles);
+            CheckFunc(x => Math.Ceiling(x), decimals);
+
+            CheckFunc(x => Math.Cos(x), doubles);
+            CheckFunc(x => Math.Cosh(x), doubles);
+            CheckFunc(x => Math.Exp(x), doubles);
+
+            CheckFunc(x => Math.Floor(x), doubles);
+            CheckFunc(x => Math.Floor(x), decimals);
+
+            CheckFunc(x => Math.Log(x), doubles);
+            CheckFunc(x => Math.Log10(x), doubles);
+
+            CheckFunc(x => Math.Pow(x, 3.7), doubles);
+
+            CheckFunc(x => Math.Round(x), doubles);
+            CheckFunc(x => Math.Round(x, 3), doubles);
+            CheckFunc(x => Math.Round(x), decimals);
+            CheckFunc(x => Math.Round(x, 3), decimals);
+
+            CheckFunc(x => Math.Sign(x), doubles);
+            CheckFunc(x => Math.Sign(x), decimals);
+            CheckFunc(x => Math.Sign(x), floats);
+            CheckFunc(x => Math.Sign(x), ints);
+            CheckFunc(x => Math.Sign(x), longs);
+            CheckFunc(x => Math.Sign(x), shorts);
+            CheckFunc(x => Math.Sign(x), sbytes);
+
+            CheckFunc(x => Math.Sin(x), doubles);
+            CheckFunc(x => Math.Sinh(x), doubles);
+            CheckFunc(x => Math.Sqrt(x), doubles);
+            CheckFunc(x => Math.Tan(x), doubles);
+            CheckFunc(x => Math.Tanh(x), doubles);
+
+            CheckFunc(x => Math.Truncate(x), doubles);
+            CheckFunc(x => Math.Truncate(x), decimals);
+
+            // Operators
+            CheckFunc(x => x * 7, doubles);
+            CheckFunc(x => x / 7, doubles);
+            CheckFunc(x => x % 7, doubles);
+            CheckFunc(x => x + 7, doubles);
+            CheckFunc(x => x - 7, doubles);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Strings.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Strings.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Strings.cs
new file mode 100644
index 0000000..7457d0a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Strings.cs
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.Text.RegularExpressions;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests strings.
+        /// </summary>
+        [Test]
+        public void TestStrings()
+        {
+            var strings = GetSecondPersonCache().AsCacheQueryable().Select(x => x.Value.Name);
+
+            CheckFunc(x => x.ToLower(), strings);
+            CheckFunc(x => x.ToUpper(), strings);
+            CheckFunc(x => x.StartsWith("Person_9"), strings);
+            CheckFunc(x => x.EndsWith("7"), strings);
+            CheckFunc(x => x.Contains("son_3"), strings);
+            CheckFunc(x => x.Length, strings);
+
+            CheckFunc(x => x.IndexOf("9"), strings);
+            CheckFunc(x => x.IndexOf("7", 4), strings);
+
+            CheckFunc(x => x.Substring(4), strings);
+            CheckFunc(x => x.Substring(4, 5), strings);
+
+            CheckFunc(x => x.Trim(), strings);
+            CheckFunc(x => x.Trim('P'), strings);
+            var toTrim = new[] { 'P' };
+            CheckFunc(x => x.Trim(toTrim), strings);
+            CheckFunc(x => x.Trim(new List<char> { 'P' }.ToArray()), strings);
+            CheckFunc(x => x.Trim('3'), strings);
+            CheckFunc(x => x.TrimStart('P'), strings);
+            CheckFunc(x => x.TrimStart(toTrim), strings);
+            CheckFunc(x => x.TrimStart('3'), strings);
+            Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimStart('P', 'e'), strings));
+            CheckFunc(x => x.TrimEnd('P'), strings);
+            CheckFunc(x => x.TrimEnd(toTrim), strings);
+            CheckFunc(x => x.TrimEnd('3'), strings);
+            var toTrimFails = new[] { 'P', 'c' };
+            Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.Trim(toTrimFails), strings));
+            Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimStart(toTrimFails), strings));
+            Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimEnd(toTrimFails), strings));
+
+            CheckFunc(x => Regex.Replace(x, @"son.\d", "kele!"), strings);
+            CheckFunc(x => x.Replace("son", ""), strings);
+            CheckFunc(x => x.Replace("son", "kele"), strings);
+
+            // Concat
+            CheckFunc(x => x + x, strings);
+
+            // String + int
+            CheckFunc(x => x + 10, strings);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSimpleName.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSimpleName.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSimpleName.cs
new file mode 100644
index 0000000..1665a64
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSimpleName.cs
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using Apache.Ignite.Core.Binary;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// LINQ test with simple name mapper.
+    /// </summary>
+    [TestFixture]
+    public class CacheLinqTestSimpleName : CacheLinqTest
+    {
+        /** <inheritdoc /> */
+        protected override IBinaryNameMapper GetNameMapper()
+        {
+            return BinaryBasicNameMapper.SimpleNameInstance;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSqlEscapeAll.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSqlEscapeAll.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSqlEscapeAll.cs
new file mode 100644
index 0000000..6b05f7b
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSqlEscapeAll.cs
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using NUnit.Framework;
+
+    /// <summary>
+    /// LINQ test with simple name mapper.
+    /// </summary>
+    [TestFixture]
+    public class CacheLinqTestSqlEscapeAll : CacheLinqTest
+    {
+        /** <inheritdoc /> */
+        protected override bool GetSqlEscapeAll()
+        {
+            return true;
+        }
+    }
+}
\ No newline at end of file


[3/3] ignite git commit: IGNITE-5532 .NET: Split CacheLinqTest into partial classes

Posted by pt...@apache.org.
IGNITE-5532 .NET: Split CacheLinqTest into partial classes

This closes #2226


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/84c7427a
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/84c7427a
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/84c7427a

Branch: refs/heads/master
Commit: 84c7427a53a8e1712b1d0b763d7539c9cb844cb6
Parents: 15613e2
Author: Sergey Stronchinskiy <gu...@gmail.com>
Authored: Tue Jul 4 14:51:25 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Jul 4 14:51:25 2017 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.Core.Tests.csproj             |   17 +-
 .../Cache/Query/CacheLinqTest.cs                | 2084 ------------------
 .../Cache/Query/CacheLinqTestSimpleName.cs      |   35 -
 .../Cache/Query/CacheLinqTestSqlEscapeAll.cs    |   34 -
 .../Query/Linq/CacheLinqTest.Aggregates.cs      |   91 +
 .../Cache/Query/Linq/CacheLinqTest.Base.cs      |  506 +++++
 .../Query/Linq/CacheLinqTest.CompiledQuery.cs   |  215 ++
 .../Cache/Query/Linq/CacheLinqTest.Contains.cs  |  128 ++
 .../Cache/Query/Linq/CacheLinqTest.Custom.cs    |  107 +
 .../Cache/Query/Linq/CacheLinqTest.DateTime.cs  |   89 +
 .../Cache/Query/Linq/CacheLinqTest.Functions.cs |  211 ++
 .../Query/Linq/CacheLinqTest.Introspection.cs   |  145 ++
 .../Linq/CacheLinqTest.Join.LocalCollection.cs  |  182 ++
 .../Cache/Query/Linq/CacheLinqTest.Join.cs      |  310 +++
 .../Cache/Query/Linq/CacheLinqTest.Misc.cs      |  350 +++
 .../Cache/Query/Linq/CacheLinqTest.Numerics.cs  |  131 ++
 .../Cache/Query/Linq/CacheLinqTest.Strings.cs   |   91 +
 .../Cache/Query/Linq/CacheLinqTestSimpleName.cs |   35 +
 .../Query/Linq/CacheLinqTestSqlEscapeAll.cs     |   34 +
 19 files changed, 2639 insertions(+), 2156 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 09eac70..71631b2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -77,6 +77,17 @@
     <Compile Include="Binary\BinarySelfTestSimpleName.cs" />
     <Compile Include="Binary\EnumsTestOnline.cs" />
     <Compile Include="Cache\PersistentStoreTest.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.CompiledQuery.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.DateTime.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Aggregates.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Join.LocalCollection.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Strings.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Functions.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Numerics.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Introspection.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Misc.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Custom.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Contains.cs" />
     <Compile Include="Deployment\GetAddressFunc.cs" />
     <Compile Include="Deployment\PeerAssemblyLoadingAllApisTest.cs" />
     <Compile Include="Deployment\PeerAssemblyLoadingVersioningTest.cs" />
@@ -110,8 +121,8 @@
     <Compile Include="Cache\Query\CacheDmlQueriesTest.cs" />
     <Compile Include="Cache\CacheAbstractTransactionalTest.cs" />
     <Compile Include="Cache\Query\CacheDmlQueriesTestSimpleName.cs" />
-    <Compile Include="Cache\Query\CacheLinqTestSqlEscapeAll.cs" />
-    <Compile Include="Cache\Query\CacheLinqTestSimpleName.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTestSqlEscapeAll.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTestSimpleName.cs" />
     <Compile Include="Cache\Query\CacheQueriesTestSimpleName.cs" />
     <Compile Include="Cache\Query\Continuous\ContinuousQueryTest.cs" />
     <Compile Include="Cache\Store\CacheStoreAdapterTest.cs" />
@@ -158,7 +169,7 @@
     <Compile Include="Cache\CachePartitionedTest.cs" />
     <Compile Include="Cache\CacheReplicatedAtomicTest.cs" />
     <Compile Include="Cache\CacheReplicatedTest.cs" />
-    <Compile Include="Cache\Query\CacheLinqTest.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Base.cs" />
     <Compile Include="Cache\Query\CacheQueriesCodeConfigurationTest.cs" />
     <Compile Include="Cache\Query\Continuous\ContinuousQueryAbstractTest.cs" />
     <Compile Include="Cache\Query\Continuous\ContinuousQueryAtomicBackupTest.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
deleted file mode 100644
index e46ae0b..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
+++ /dev/null
@@ -1,2084 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// ReSharper disable SuspiciousTypeConversion.Global
-// ReSharper disable MemberCanBePrivate.Global
-// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
-// ReSharper disable UnusedAutoPropertyAccessor.Global
-// ReSharper disable StringIndexOfIsCultureSpecific.1
-// ReSharper disable StringIndexOfIsCultureSpecific.2
-// ReSharper disable StringCompareToIsCultureSpecific
-// ReSharper disable StringCompareIsCultureSpecific.1
-// ReSharper disable UnusedMemberInSuper.Global
-namespace Apache.Ignite.Core.Tests.Cache.Query
-{
-    using System;
-    using System.Collections;
-    using System.Collections.Generic;
-    using System.Linq;
-    using System.Linq.Expressions;
-    using System.Text.RegularExpressions;
-    using System.Threading;
-    using Apache.Ignite.Core.Binary;
-    using Apache.Ignite.Core.Cache;
-    using Apache.Ignite.Core.Cache.Configuration;
-    using Apache.Ignite.Core.Cache.Query;
-    using Apache.Ignite.Core.Common;
-    using Apache.Ignite.Linq;
-    using NUnit.Framework;
-
-    /// <summary>
-    /// Tests LINQ.
-    /// </summary>
-    public class CacheLinqTest
-    {
-        /** Cache name. */
-        private const string PersonOrgCacheName = "person_org";
-
-        /** Cache name. */
-        private const string PersonSecondCacheName = "person_cache";
-
-        /** Role cache name. */
-        private const string RoleCacheName = "role_cache";
-
-        /** */
-        private const int RoleCount = 3;
-
-        /** */
-        private const int PersonCount = 900;
-
-        /** */
-        private bool _runDbConsole;
-
-        /** */
-        private static readonly DateTime StartDateTime = new DateTime(2000, 5, 17, 15, 4, 5, DateTimeKind.Utc);
-
-        /// <summary>
-        /// Fixture set up.
-        /// </summary>
-        [TestFixtureSetUp]
-        public void FixtureSetUp()
-        {
-            _runDbConsole = false;  // set to true to open H2 console
-
-            if (_runDbConsole)
-                Environment.SetEnvironmentVariable("IGNITE_H2_DEBUG_CONSOLE", "true");
-
-            Ignition.Start(GetConfig());
-            Ignition.Start(GetConfig("grid2"));
-
-            // Populate caches
-            var cache = GetPersonCache();
-            var personCache = GetSecondPersonCache();
-
-            for (var i = 0; i < PersonCount; i++)
-            {
-                cache.Put(i, new Person(i, string.Format(" Person_{0}  ", i))
-                {
-                    Address = new Address {Zip = i, Street = "Street " + i, AliasTest = i},
-                    OrganizationId = i%2 + 1000,
-                    Birthday = StartDateTime.AddYears(i),
-                    AliasTest = -i
-                });
-
-                var i2 = i + PersonCount;
-                personCache.Put(i2, new Person(i2, "Person_" + i2)
-                {
-                    Address = new Address {Zip = i2, Street = "Street " + i2},
-                    OrganizationId = i%2 + 1000,
-                    Birthday = StartDateTime.AddYears(i)
-                });
-            }
-
-            var orgCache = GetOrgCache();
-
-            orgCache[1000] = new Organization {Id = 1000, Name = "Org_0"};
-            orgCache[1001] = new Organization {Id = 1001, Name = "Org_1"};
-            orgCache[1002] = new Organization {Id = 1002, Name = null};
-
-            var roleCache = GetRoleCache();
-
-            roleCache[new RoleKey(1, 101)] = new Role {Name = "Role_1", Date = StartDateTime};
-            roleCache[new RoleKey(2, 102)] = new Role {Name = "Role_2", Date = StartDateTime.AddYears(1)};
-            roleCache[new RoleKey(3, 103)] = new Role {Name = null, Date = StartDateTime.AddHours(5432)};
-        }
-
-        /// <summary>
-        /// Gets the configuration.
-        /// </summary>
-        private IgniteConfiguration GetConfig(string gridName = null)
-        {
-            return new IgniteConfiguration(TestUtils.GetTestConfiguration())
-            {
-                BinaryConfiguration = new BinaryConfiguration(typeof(Person),
-                    typeof(Organization), typeof(Address), typeof(Role), typeof(RoleKey), typeof(Numerics))
-                {
-                    NameMapper = GetNameMapper()
-                },
-                IgniteInstanceName = gridName
-            };
-        }
-
-        /// <summary>
-        /// Gets the name mapper.
-        /// </summary>
-        protected virtual IBinaryNameMapper GetNameMapper()
-        {
-            return BinaryBasicNameMapper.FullNameInstance;
-        }
-
-        /// <summary>
-        /// Gets the SqlEscapeAll setting.
-        /// </summary>
-        protected virtual bool GetSqlEscapeAll()
-        {
-            return false;
-        }
-
-        /// <summary>
-        /// Fixture tear down.
-        /// </summary>
-        [TestFixtureTearDown]
-        public void FixtureTearDown()
-        {
-            if (_runDbConsole)
-                Thread.Sleep(Timeout.Infinite);
-            Ignition.StopAll(true);
-        }
-
-        /// <summary>
-        /// Tests the empty query.
-        /// </summary>
-        [Test]
-        public void TestEmptyQuery()
-        {
-            // There are both persons and organizations in the same cache, but query should only return specific type
-            Assert.AreEqual(PersonCount, GetPersonCache().AsCacheQueryable().ToArray().Length);
-            Assert.AreEqual(RoleCount, GetRoleCache().AsCacheQueryable().ToArray().Length);
-        }
-
-        /// <summary>
-        /// Tests where clause.
-        /// </summary>
-        [Test]
-        public void TestWhere()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-
-            // Test const and var parameters
-            const int age = 10;
-            var key = 15;
-
-            Assert.AreEqual(age, cache.Where(x => x.Value.Age < age).ToArray().Length);
-            Assert.AreEqual(age, cache.Where(x => x.Value.Address.Zip < age).ToArray().Length);
-            Assert.AreEqual(19, cache.Where(x => x.Value.Age > age && x.Value.Age < 30).ToArray().Length);
-            Assert.AreEqual(20, cache.Where(x => x.Value.Age > age).Count(x => x.Value.Age < 30 || x.Value.Age == 50));
-            Assert.AreEqual(key, cache.Where(x => x.Key < key).ToArray().Length);
-            Assert.AreEqual(key, cache.Where(x => -x.Key > -key).ToArray().Length);
-
-            Assert.AreEqual(1, GetRoleCache().AsCacheQueryable().Where(x => x.Key.Foo < 2).ToArray().Length);
-            Assert.AreEqual(2, GetRoleCache().AsCacheQueryable().Where(x => x.Key.Bar > 2 && x.Value.Name != "11")
-                .ToArray().Length);
-        }
-
-        /// <summary>
-        /// Tests the single field query.
-        /// </summary>
-        [Test]
-        public void TestSingleFieldQuery()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-
-            // Multiple values
-            Assert.AreEqual(new[] {0, 1, 2},
-                cache.Where(x => x.Key < 3).Select(x => x.Value.Address.Zip).ToArray());
-
-            // Single value
-            Assert.AreEqual(0, cache.Where(x => x.Key < 0).Select(x => x.Value.Age).FirstOrDefault());
-            Assert.AreEqual(3, cache.Where(x => x.Key == 3).Select(x => x.Value.Age).FirstOrDefault());
-            Assert.AreEqual(3, cache.Where(x => x.Key == 3).Select(x => x.Value).Single().Age);
-            Assert.AreEqual(3, cache.Select(x => x.Key).Single(x => x == 3));
-            Assert.AreEqual(7,
-                cache.Select(x => x.Value)
-                    .Where(x => x.Age == 7)
-                    .Select(x => x.Address)
-                    .Where(x => x.Zip > 0)
-                    .Select(x => x.Zip)
-                    .Single());
-        }
-
-        /// <summary>
-        /// Tests the field projection.
-        /// </summary>
-        [Test]
-        public void TestFieldProjection()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-
-            // Project whole cache entry to anonymous class
-            Assert.AreEqual(5, cache.Where(x => x.Key == 5).Select(x => new { Foo = x }).Single().Foo.Key);
-        }
-
-        /// <summary>
-        /// Tests the multi field query.
-        /// </summary>
-        [Test]
-        public void TestMultiFieldQuery()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-
-            // Test anonymous type (ctor invoke)
-            var data = cache
-                .Select(x => new {Id = x.Key + 20, Age_ = x.Value.Age + 10, Addr = x.Value.Address})
-                .Where(x => x.Id < 25)
-                .ToArray();
-
-            Assert.AreEqual(5, data.Length);
-
-            foreach (var t in data)
-            {
-                Assert.AreEqual(t.Age_ - 10, t.Id - 20);
-                Assert.AreEqual(t.Age_ - 10, t.Addr.Zip);
-            }
-        }
-
-        /// <summary>
-        /// Tests the scalar query.
-        /// </summary>
-        [Test]
-        public void TestScalarQuery()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-
-            Assert.AreEqual(PersonCount - 1, cache.Max(x => x.Value.Age));
-            Assert.AreEqual(0, cache.Min(x => x.Value.Age));
-
-            Assert.AreEqual(21, cache.Where(x => x.Key > 5 && x.Value.Age < 9).Select(x => x.Value.Age).Sum());
-
-            Assert.AreEqual(PersonCount, cache.Count());
-            Assert.AreEqual(PersonCount, cache.Count(x => x.Key < PersonCount));
-        }
-
-        /// <summary>
-        /// Tests strings.
-        /// </summary>
-        [Test]
-        public void TestStrings()
-        {
-            var strings = GetSecondPersonCache().AsCacheQueryable().Select(x => x.Value.Name);
-
-            CheckFunc(x => x.ToLower(), strings);
-            CheckFunc(x => x.ToUpper(), strings);
-            CheckFunc(x => x.StartsWith("Person_9"), strings);
-            CheckFunc(x => x.EndsWith("7"), strings);
-            CheckFunc(x => x.Contains("son_3"), strings);
-            CheckFunc(x => x.Length, strings);
-
-            CheckFunc(x => x.IndexOf("9"), strings);
-            CheckFunc(x => x.IndexOf("7", 4), strings);
-
-            CheckFunc(x => x.Substring(4), strings);
-            CheckFunc(x => x.Substring(4, 5), strings);
-
-            CheckFunc(x => x.Trim(), strings);
-            CheckFunc(x => x.Trim('P'), strings);
-            var toTrim = new[] {'P'};
-            CheckFunc(x => x.Trim(toTrim), strings);
-            CheckFunc(x => x.Trim(new List<char> {'P'}.ToArray()), strings);
-            CheckFunc(x => x.Trim('3'), strings);
-            CheckFunc(x => x.TrimStart('P'), strings);
-            CheckFunc(x => x.TrimStart(toTrim), strings);
-            CheckFunc(x => x.TrimStart('3'), strings);
-            Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimStart('P', 'e'), strings));
-            CheckFunc(x => x.TrimEnd('P'), strings);
-            CheckFunc(x => x.TrimEnd(toTrim), strings);
-            CheckFunc(x => x.TrimEnd('3'), strings);
-            var toTrimFails = new[] {'P', 'c'};
-            Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.Trim(toTrimFails), strings));
-            Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimStart(toTrimFails), strings));
-            Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimEnd(toTrimFails), strings));
-
-            CheckFunc(x => Regex.Replace(x, @"son.\d", "kele!"), strings);
-            CheckFunc(x => x.Replace("son", ""), strings);
-            CheckFunc(x => x.Replace("son", "kele"), strings);
-
-            // Concat
-            CheckFunc(x => x + x, strings);
-
-            // String + int
-            CheckFunc(x => x + 10, strings);
-        }
-
-        /// <summary>
-        /// Tests aggregates.
-        /// </summary>
-        [Test]
-        public void TestAggregates()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-
-            Assert.AreEqual(PersonCount, cache.Count());
-            Assert.AreEqual(PersonCount, cache.Select(x => x.Key).Count());
-            Assert.AreEqual(2, cache.Select(x => x.Value.OrganizationId).Distinct().Count());
-
-            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
-            Assert.Throws<NotSupportedException>(() => cache.Select(x => new {x.Key, x.Value}).Count());
-
-            // Min/max/sum/avg
-            var ints = cache.Select(x => x.Key);
-            Assert.AreEqual(0, ints.Min());
-            Assert.AreEqual(PersonCount - 1, ints.Max());
-            Assert.AreEqual(ints.ToArray().Sum(), ints.Sum());
-            Assert.AreEqual((int)ints.ToArray().Average(), (int)ints.Average());
-
-            var dupInts = ints.Select(x => x/10);  // duplicate values
-            CollectionAssert.AreEquivalent(dupInts.ToArray().Distinct().ToArray(), dupInts.Distinct().ToArray());
-            Assert.AreEqual(dupInts.ToArray().Distinct().Sum(), dupInts.Distinct().Sum());
-
-            // All/any
-            Assert.IsFalse(ints.Where(x => x > -5).Any(x => x > PersonCount && x > 0));
-            Assert.IsTrue(ints.Any(x => x < PersonCount / 2));
-
-            // Skip/take
-            var keys = cache.Select(x => x.Key).OrderBy(x => x);
-            Assert.AreEqual(new[] {0, 1}, keys.Take(2).ToArray());
-            Assert.AreEqual(new[] {1, 2}, keys.Skip(1).Take(2).ToArray());
-            Assert.AreEqual(new[] {PersonCount - 2, PersonCount - 1}, keys.Skip(PersonCount - 2).ToArray());
-        }
-
-        /// <summary>
-        /// Tests aggregates with all clause.
-        /// </summary>
-        [Test]
-        public void TestAggregatesAll()
-        {
-            var ints = GetPersonCache().AsCacheQueryable().Select(x => x.Key);
-
-            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
-            var ex = Assert.Throws<NotSupportedException>(() => ints.Where(x => x > -10)
-                .All(x => x < PersonCount && x >= 0));
-
-            Assert.IsTrue(ex.Message.StartsWith("Operator is not supported: All"));
-        }
-
-        /// <summary>
-        /// Tests conditions.
-        /// </summary>
-        [Test]
-        public void TestConditions()
-        {
-            TestConditional("even", "odd");
-            TestConditional(new Address { Zip = 99999 }, new Address { Zip = 7777777 }, (a1, a2) => a1.Zip == a2.Zip);
-            TestConditional(new RoleKey(int.MaxValue, long.MinValue), new RoleKey(int.MinValue, long.MaxValue));
-            TestConditionalWithNullableStructs<int>();
-            TestConditionalWithNullableStructs<uint>();
-            TestConditionalWithNullableStructs<Guid>();
-            TestConditionalWithNullableStructs<byte>();
-            TestConditionalWithNullableStructs<sbyte>();
-            TestConditionalWithNullableStructs<short>();
-            TestConditionalWithNullableStructs<ushort>();
-            TestConditionalWithNullableStructs<bool>();
-            TestConditionalWithNullableStructs<long>();
-            TestConditionalWithNullableStructs<ulong>();
-            TestConditionalWithNullableStructs<double>();
-            TestConditionalWithNullableStructs<float>();
-            TestConditionalWithNullableStructs<decimal>();
-            TestConditionalWithNullableStructs<DateTime>(DateTime.UtcNow);
-
-            var charException = Assert.Throws<NotSupportedException>(() => TestConditionalWithNullableStructs<char>());
-            Assert.AreEqual("Type is not supported for SQL mapping: System.Char", charException.Message);
-
-            var roles = GetRoleCache().AsCacheQueryable();
-            CheckFunc(x => x.Value.Name ?? "def_name", roles);
-        }
-
-        /// <summary>
-        /// Tests the same cache join.
-        /// </summary>
-        [Test]
-        public void TestSameCacheJoin()
-        {
-            // Select persons in specific organization
-            var organizations = GetOrgCache().AsCacheQueryable();
-            var persons = GetPersonCache().AsCacheQueryable();
-
-            var res = persons.Join(organizations, person => person.Value.OrganizationId + 3, org => org.Value.Id + 3,
-                (person, org) => new {Person = person.Value, Org = org.Value})
-                .Where(x => x.Org.Name == "Org_1")
-                .ToList();
-
-            Assert.AreEqual(PersonCount / 2, res.Count);
-
-            Assert.IsTrue(res.All(r => r.Person.OrganizationId == r.Org.Id));
-
-            // Test full projection (selects pair of ICacheEntry)
-            var res2 = persons.Join(organizations, person => person.Value.OrganizationId - 1, org => org.Value.Id - 1,
-                (person, org) => new {Person = person, Org = org})
-                .Where(x => x.Org.Value.Name.ToLower() == "org_0")
-                .ToList();
-
-            Assert.AreEqual(PersonCount / 2, res2.Count);
-        }
-
-        /// <summary>
-        /// Tests the multi key join.
-        /// </summary>
-        [Test]
-        public void TestMultiKeyJoin()
-        {
-            var organizations = GetOrgCache().AsCacheQueryable();
-            var persons = GetPersonCache().AsCacheQueryable();
-
-            var multiKey =
-                from person in persons
-                join org in organizations on
-                    new { OrgId = person.Value.OrganizationId, person.Key } equals
-                    new { OrgId = org.Value.Id, Key = org.Key - 1000 }
-                where person.Key == 1
-                select new { PersonName = person.Value.Name, OrgName = org.Value.Name };
-
-            Assert.AreEqual(" Person_1  ", multiKey.Single().PersonName);
-        }
-
-        /// <summary>
-        /// Tests the cross cache join.
-        /// </summary>
-        [Test]
-        public void TestCrossCacheJoin()
-        {
-            var persons = GetPersonCache().AsCacheQueryable();
-            var roles = GetRoleCache().AsCacheQueryable();
-
-            var res = persons.Join(roles, person => person.Key, role => role.Key.Foo, (person, role) => role)
-                .OrderBy(x => x.Key.Bar)
-                .ToArray();
-
-            Assert.AreEqual(RoleCount, res.Length);
-            Assert.AreEqual(101, res[0].Key.Bar);
-        }
-
-        /// <summary>
-        /// Tests the cross cache join.
-        /// </summary>
-        [Test]
-        public void TestCrossCacheJoinInline()
-        {
-            var res = GetPersonCache().AsCacheQueryable().Join(GetRoleCache().AsCacheQueryable(), 
-                person => person.Key, role => role.Key.Foo, (person, role) => role)
-                .OrderBy(x => x.Key.Bar).ToArray();
-
-            Assert.AreEqual(RoleCount, res.Length);
-            Assert.AreEqual(101, res[0].Key.Bar);
-        }
-
-        /// <summary>
-        /// Tests the multi cache join.
-        /// </summary>
-        [Test]
-        public void TestMultiCacheJoin()
-        {
-            var organizations = GetOrgCache().AsCacheQueryable();
-            var persons = GetPersonCache().AsCacheQueryable();
-            var roles = GetRoleCache().AsCacheQueryable();
-
-            var res = roles.Join(persons, role => role.Key.Foo, person => person.Key,
-                (role, person) => new {person, role})
-                .Join(organizations, pr => pr.person.Value.OrganizationId, org => org.Value.Id,
-                    (pr, org) => new {org, pr.person, pr.role}).ToArray();
-
-            Assert.AreEqual(RoleCount, res.Length);
-        }
-
-        /// <summary>
-        /// Tests the multi cache join subquery.
-        /// </summary>
-        [Test]
-        public void TestMultiCacheJoinSubquery()
-        {
-            var organizations = GetOrgCache().AsCacheQueryable().Where(x => x.Key == 1001);
-            var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < 20);
-            var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Key.Foo >= 0);
-
-            var res = roles.Join(persons, role => role.Key.Foo, person => person.Key,
-                (role, person) => new {person, role})
-                .Join(organizations, pr => pr.person.Value.OrganizationId, org => org.Value.Id,
-                    (pr, org) => new {org, pr.person, pr.role}).ToArray();
-
-            Assert.AreEqual(2, res.Length);
-        }
-
-        /// <summary>
-        /// Tests the outer join.
-        /// </summary>
-        [Test]
-        public void TestOuterJoin()
-        {
-            var persons = GetPersonCache().AsCacheQueryable();
-            var roles = GetRoleCache().AsCacheQueryable();
-
-            var res = persons.Join(roles.Where(r => r.Key.Bar > 0).DefaultIfEmpty(),
-                person => person.Key, role => role.Key.Foo,
-                (person, role) => new
-                {
-                    PersonName = person.Value.Name,
-                    RoleName = role.Value.Name
-                })
-                .Where(x => x.PersonName != " ")
-                .ToArray();
-
-            Assert.AreEqual(PersonCount, res.Length);
-        }
-
-        /// <summary>
-        /// Tests the subquery join.
-        /// </summary>
-        [Test]
-        public void TestSubqueryJoin()
-        {
-            var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key >= 0);
-
-            var orgs = GetOrgCache().AsCacheQueryable().Where(x => x.Key > 10);
-
-            var qry1 = persons.Join(orgs,
-                    p => p.Value.OrganizationId,
-                    o => o.Value.Id, 
-                    (p, o) => p)
-                .Where(x => x.Key >= 0)
-                .ToList();
-
-            Assert.AreEqual(PersonCount, qry1.Count);
-
-            // With selector inline
-            var qry2 = persons
-                .Join(orgs.Select(orgEntry => orgEntry.Key),
-                    e => e.Value.OrganizationId,
-                    i => i,
-                    (e, i) => e)
-                .ToList();
-
-            Assert.AreEqual(PersonCount, qry2.Count);
-
-            // With selector from variable
-            var innerSequence = orgs
-                .Select(orgEntry => orgEntry.Key);
-
-            var qry3 = persons
-                .Join(innerSequence,
-                    e => e.Value.OrganizationId,
-                    i => i,
-                    (e, i) => e)
-                .ToList();
-
-            Assert.AreEqual(PersonCount, qry3.Count);
-        }
-
-        /// <summary>
-        /// Tests the join with local collection.
-        /// </summary>
-        [Test]
-        public void TestLocalJoin()
-        {
-            var persons = GetPersonCache().AsCacheQueryable();
-            var orgs = GetOrgCache().AsCacheQueryable();
-
-            var localOrgs = orgs
-                .Select(e => e.Value)
-                .ToArray();
-
-            var allOrganizationIds = localOrgs
-                .Select(e => e.Id)
-                .ToArray();
-
-            // Join with local collection 
-            var qry1 = persons.Join(allOrganizationIds,
-                    pe => pe.Value.OrganizationId,
-                    i => i,
-                    (pe, o) => pe
-                )
-                .ToArray();
-
-            Assert.AreEqual(PersonCount, qry1.Length);
-
-            // Join using expression in innerKeySelector
-            var qry2 = persons.Join(allOrganizationIds,
-                    pe => pe.Value.OrganizationId,
-                    i => i + 1 - 1,
-                    (pe, o) => pe
-                )
-                .ToArray();
-
-            Assert.AreEqual(PersonCount, qry2.Length);
-
-            // Local collection subquery
-            var qry3 = persons.Join(localOrgs.Select(e => e.Id),
-                    pe => pe.Value.OrganizationId,
-                    i => i,
-                    (pe, o) => pe
-                )
-                .ToArray();
-
-            Assert.AreEqual(PersonCount, qry3.Length);
-
-            // Compiled query
-            var qry4 = CompiledQuery.Compile(() => persons.Join(allOrganizationIds,
-                pe => pe.Value.OrganizationId,
-                i => i,
-                (pe, o) => pe
-            ));
-
-            Assert.AreEqual(PersonCount, qry4().Count());
-
-            // Compiled query with outer join
-            var qry4A = CompiledQuery.Compile(() => persons.Join(new int[] {}.DefaultIfEmpty(),
-                pe => pe.Value.OrganizationId,
-                i => i,
-                (pe, o) => pe
-            ));
-
-            Assert.AreEqual(PersonCount, qry4A().Count());
-
-            // Compiled query
-            var qry5 = CompiledQuery.Compile(() => persons.Join(new[] { -1, -2 }.DefaultIfEmpty(),
-                pe => pe.Value.OrganizationId,
-                i => i,
-                (pe, o) => pe
-            ));
-
-            Assert.AreEqual(PersonCount, qry5().Count());
-
-            // Outer join
-            var qry6 = persons.Join(new[] { -1, -2 }.DefaultIfEmpty(),
-                    pe => pe.Value.OrganizationId,
-                    i => i,
-                    (pe, o) => pe
-                )
-                .ToArray();
-
-            Assert.AreEqual(PersonCount, qry6.Length);
-
-            // Join with local list
-            var qry7 = persons.Join(new List<int> {1000, 1001, 1002, 1003},
-                    pe => pe.Value.OrganizationId,
-                    i => i,
-                    (pe, o) => pe
-                )
-                .ToArray();
-
-            Assert.AreEqual(PersonCount, qry7.Length);
-
-            // Join with local list variable
-            var list = new List<int> { 1000, 1001, 1002, 1003 };
-            var qry8 = persons.Join(list,
-                    pe => pe.Value.OrganizationId,
-                    i => i,
-                    (pe, o) => pe
-                )
-                .ToArray();
-
-            Assert.AreEqual(PersonCount, qry8.Length);
-        }
-
-        /// <summary>
-        /// Tests the compiled query containing join with local collection passed as parameter.
-        /// </summary>
-        [Test]
-        [Ignore("IGNITE-5404")]
-        public void TestLocalJoinCompiledQueryParameter()
-        {
-            var persons = GetPersonCache().AsCacheQueryable();
-            var orgs = GetOrgCache().AsCacheQueryable();
-
-            var localOrgs = orgs
-                .Select(e => e.Value)
-                .ToArray();
-
-            var allOrganizationIds = localOrgs
-                .Select(e => e.Id)
-                .ToArray();
-
-            // Join with local collection passed as parameter
-            var qry1 = CompiledQuery.Compile((IEnumerable<int> lc) => persons.Join(lc,
-                pe => pe.Value.OrganizationId,
-                i => i,
-                (pe, o) => pe
-            ));
-
-            Assert.AreEqual(PersonCount, qry1(allOrganizationIds).Count());
-
-            //Compiled query with outer join
-            var qry2 = CompiledQuery.Compile((IEnumerable<int> lc) => persons.Join(lc.DefaultIfEmpty(),
-                pe => pe.Value.OrganizationId,
-                i => i,
-                (pe, o) => pe
-            ));
-
-            Assert.AreEqual(PersonCount, qry2(new[] { -11 }).Count());
-        }
-
-        /// <summary>
-        /// Tests the invalid join.
-        /// </summary>
-        [Test]
-        public void TestInvalidJoin()
-        {
-            var localComplexTypeCollection = GetOrgCache().AsCacheQueryable()
-                .Select(e => e.Value)
-                .ToArray();
-
-            // Join on non-IQueryable with complex(not supported) type
-            var ex = Assert.Throws<NotSupportedException>(() =>
-                // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
-            {
-                GetPersonCache().AsCacheQueryable().Join(localComplexTypeCollection, p => p.Value.OrganizationId, 
-                    o => o.Id, (p, o) => p).ToList();
-            });
-
-            Assert.IsTrue(ex.Message.StartsWith("Not supported item type for Join with local collection"));
-        }
-
-        /// <summary>
-        /// Tests query with multiple from clause.
-        /// </summary>
-        [Test]
-        public void TestMultipleFrom()
-        {
-            var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < PersonCount);
-            var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Value.Name != "1");
-
-            var all = persons.SelectMany(person => roles.Select(role => new { role, person }));
-            Assert.AreEqual(RoleCount * PersonCount, all.Count());
-
-            var filtered = 
-                from person in persons
-                from role in roles
-                where person.Key == role.Key.Foo
-                select new {Person = person.Value.Name, Role = role.Value.Name};
-
-            var res = filtered.ToArray();
-
-            Assert.AreEqual(RoleCount, res.Length);
-        }
-
-        /// <summary>
-        /// Tests query with multiple from clause with inline query sources.
-        /// </summary>
-        [Test]
-        public void TestMultipleFromInline()
-        {
-            var filtered =
-                from person in GetPersonCache().AsCacheQueryable()
-                from role in GetRoleCache().AsCacheQueryable()
-                where person.Key == role.Key.Foo
-                select new {Person = person.Value.Name, Role = role.Value.Name};
-
-            var res = filtered.ToArray();
-
-            Assert.AreEqual(RoleCount, res.Length);
-        }
-
-        /// <summary>
-        /// Tests the join of a table to itself.
-        /// </summary>
-        [Test]
-        public void TestSelfJoin()
-        {
-            // Different queryables
-            var p1 = GetPersonCache().AsCacheQueryable();
-            var p2 = GetPersonCache().AsCacheQueryable();
-
-            var qry = p1.Join(p2, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
-            Assert.AreEqual(PersonCount, qry.ToArray().Distinct().Count());
-
-            // Same queryables
-            var qry2 = p1.Join(p1, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
-            Assert.AreEqual(PersonCount, qry2.ToArray().Distinct().Count());
-        }
-
-        /// <summary>
-        /// Tests the join of a table to itself with inline queryable.
-        /// </summary>
-        [Test]
-        public void TestSelfJoinInline()
-        {
-            var qry = GetPersonCache().AsCacheQueryable().Join(GetPersonCache().AsCacheQueryable(), 
-                x => x.Value.Age, x => x.Key, (x, y) => x.Key);
-
-            Assert.AreEqual(PersonCount, qry.ToArray().Distinct().Count());
-        }
-
-        /// <summary>
-        /// Tests the SelectMany from field collection.
-        /// </summary>
-        [Test]
-        public void TestSelectManySameTable()
-        {
-            var persons = GetPersonCache().AsCacheQueryable();
-
-            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
-            var ex = Assert.Throws<NotSupportedException>(() => persons.SelectMany(x => x.Value.Name).ToArray());
-
-            Assert.IsTrue(ex.Message.StartsWith("FROM clause must be IQueryable: from Char"));
-        }
-
-        /// <summary>
-        /// Tests the group by.
-        /// </summary>
-        [Test]
-        public void TestGroupBy()
-        {
-            var persons = GetPersonCache().AsCacheQueryable();
-            var orgs = GetOrgCache().AsCacheQueryable();
-
-            // Simple, unordered
-            CollectionAssert.AreEquivalent(new[] {1000, 1001},
-                persons.GroupBy(x => x.Value.OrganizationId).Select(x => x.Key).ToArray());
-
-            // Aggregate
-            Assert.AreEqual(1000,
-                persons.GroupBy(x => x.Value.OrganizationId).Select(x => x.Key).OrderBy(x => x).First());
-
-            // Ordering and count
-            var res1 =
-                from p in persons
-                orderby p.Value.Name
-                group p by p.Value.OrganizationId
-                into gs
-                orderby gs.Key
-                where gs.Count() > 10
-                select new {Count = gs.Count(), OrgId = gs.Key, AvgAge = gs.Average(x => x.Value.Age)};
-
-            var resArr = res1.ToArray();
-
-            Assert.AreEqual(new[]
-            {
-                new {Count = PersonCount/2, OrgId = 1000, AvgAge = (double) PersonCount/2 - 1},
-                new {Count = PersonCount/2, OrgId = 1001, AvgAge = (double) PersonCount/2}
-            }, resArr);
-
-            // Join and sum
-            var res2 = persons.Join(orgs.Where(o => o.Key > 10), p => p.Value.OrganizationId, o => o.Key,
-                (p, o) => new {p, o})
-                .GroupBy(x => x.o.Value.Name)
-                .Select(g => new {Org = g.Key, AgeSum = g.Select(x => x.p.Value.Age).Sum()});
-
-            var resArr2 = res2.ToArray();
-
-            Assert.AreEqual(new[]
-            {
-                new {Org = "Org_0", AgeSum = persons.Where(x => x.Value.OrganizationId == 1000).Sum(x => x.Value.Age)},
-                new {Org = "Org_1", AgeSum = persons.Where(x => x.Value.OrganizationId == 1001).Sum(x => x.Value.Age)}
-            }, resArr2);
-        }
-
-        /// <summary>
-        /// Tests the union.
-        /// </summary>
-        [Test]
-        public void TestUnion()
-        {
-            // Direct union
-            var persons = GetPersonCache().AsCacheQueryable();
-            var persons2 = GetSecondPersonCache().AsCacheQueryable();
-
-            var res = persons.Union(persons2).ToArray();
-
-            Assert.AreEqual(PersonCount * 2, res.Length);
-
-            // Subquery
-            var roles = GetRoleCache().AsCacheQueryable().Select(x => -x.Key.Foo);
-            var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Union(roles).ToArray();
-
-            Assert.AreEqual(RoleCount + PersonCount, ids.Length);
-        }
-
-        /// <summary>
-        /// Tests intersect.
-        /// </summary>
-        [Test]
-        public void TestIntersect()
-        {
-            // Direct intersect
-            var persons = GetPersonCache().AsCacheQueryable();
-            var persons2 = GetSecondPersonCache().AsCacheQueryable();
-
-            var res = persons.Intersect(persons2).ToArray();
-
-            Assert.AreEqual(0, res.Length);
-
-            // Subquery
-            var roles = GetRoleCache().AsCacheQueryable().Select(x => x.Key.Foo);
-            var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Intersect(roles).ToArray();
-
-            Assert.AreEqual(RoleCount, ids.Length);
-        }
-
-        /// <summary>
-        /// Tests except.
-        /// </summary>
-        [Test]
-        public void TestExcept()
-        {
-            // Direct except
-            var persons = GetPersonCache().AsCacheQueryable();
-            var persons2 = GetSecondPersonCache().AsCacheQueryable();
-
-            var res = persons.Except(persons2).ToArray();
-
-            Assert.AreEqual(PersonCount, res.Length);
-
-            // Subquery
-            var roles = GetRoleCache().AsCacheQueryable().Select(x => x.Key.Foo);
-            var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Except(roles).ToArray();
-
-            Assert.AreEqual(PersonCount - RoleCount, ids.Length);
-        }
-
-        /// <summary>
-        /// Tests ordering.
-        /// </summary>
-        [Test]
-        public void TestOrdering()
-        {
-            var persons = GetPersonCache().AsCacheQueryable()
-                .OrderByDescending(x => x.Key)
-                .ThenBy(x => x.Value.Age)
-                .ToArray();
-
-            Assert.AreEqual(Enumerable.Range(0, PersonCount).Reverse().ToArray(), 
-                persons.Select(x => x.Key).ToArray());
-
-            var personsByOrg = GetPersonCache().AsCacheQueryable()
-                .Join(GetOrgCache().AsCacheQueryable(), p => p.Value.OrganizationId, o => o.Value.Id,
-                    (p, o) => new
-                    {
-                        PersonId = p.Key,
-                        PersonName = p.Value.Name.ToUpper(),
-                        OrgName = o.Value.Name
-                    })
-                .OrderBy(x => x.OrgName.ToLower())
-                .ThenBy(x => x.PersonName)
-                .ToArray();
-
-            var expectedIds = Enumerable.Range(0, PersonCount)
-                .OrderBy(x => (x%2).ToString())
-                .ThenBy(x => x.ToString())
-                .ToArray();
-
-            var actualIds = personsByOrg.Select(x => x.PersonId).ToArray();
-
-            Assert.AreEqual(expectedIds, actualIds);
-        }
-
-        /// <summary>
-        /// Tests IEnumerable.Contains.
-        /// </summary>
-        [Test]
-        public void TestContains()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-            var orgCache = GetOrgCache().AsCacheQueryable();
-
-            var keys = new[] { 1, 2, 3 };
-            var emptyKeys = new int[0];
-
-            var bigNumberOfKeys = 10000;
-            var aLotOfKeys = Enumerable.Range(-bigNumberOfKeys + 10 - PersonCount, bigNumberOfKeys + PersonCount)
-                .ToArray();
-            var hashSetKeys = new HashSet<int>(keys);
-            var defferedCollection = Enumerable.Range(1, 10)
-                .Select(i => new {Id = i})
-                .Select(arg => arg.Id);
-
-            CheckWhereFunc(cache, e => new[] { 1, 2, 3 }.Contains(e.Key));
-            CheckWhereFunc(cache, e => emptyKeys.Contains(e.Key));
-            CheckWhereFunc(cache, e => new int[0].Contains(e.Key));
-            CheckWhereFunc(cache, e => new int[0].Contains(e.Key));
-            CheckWhereFunc(cache, e => new List<int> { 1, 2, 3 }.Contains(e.Key));
-            CheckWhereFunc(cache, e => new List<int>(keys).Contains(e.Key));
-            CheckWhereFunc(cache, e => aLotOfKeys.Contains(e.Key));
-            CheckWhereFunc(cache, e => hashSetKeys.Contains(e.Key));
-            CheckWhereFunc(cache, e => !keys.Contains(e.Key));
-            CheckWhereFunc(cache, e => defferedCollection.Contains(e.Key));
-            CheckWhereFunc(orgCache, e => new[] { "Org_1", "NonExistentName", null }.Contains(e.Value.Name));
-            CheckWhereFunc(orgCache, e => !new[] { "Org_1", "NonExistentName", null }.Contains(e.Value.Name));
-            CheckWhereFunc(orgCache, e => new[] { "Org_1", null, null }.Contains(e.Value.Name));
-            CheckWhereFunc(orgCache, e => !new[] { "Org_1", null, null }.Contains(e.Value.Name));
-            CheckWhereFunc(orgCache, e => new string[] { null }.Contains(e.Value.Name));
-            CheckWhereFunc(orgCache, e => !new string[] { null }.Contains(e.Value.Name));
-            CheckWhereFunc(orgCache, e => !new string[] { null, null }.Contains(e.Value.Name));
-            CheckWhereFunc(orgCache, e => new string[] { null, null }.Contains(e.Value.Name));
-
-            //check passing a null object as collection
-            int[] nullKeys = null;
-            var nullKeysEntries = cache
-                .Where(e => nullKeys.Contains(e.Key))
-                .ToArray();
-            Assert.AreEqual(0, nullKeysEntries.Length, "Evaluating 'null.Contains' should return zero results");
-
-
-            Func<int[]> getKeysFunc = () => null;
-            var funcNullKeyEntries = cache
-                .Where(e => getKeysFunc().Contains(e.Key))
-                .ToArray();
-            Assert.AreEqual(0, funcNullKeyEntries.Length, "Evaluating 'null.Contains' should return zero results");
-
-
-            // Check subselect from other cache
-            var subSelectCount = cache
-                .Count(entry => orgCache
-                    .Where(orgEntry => orgEntry.Value.Name == "Org_1")
-                    .Select(orgEntry => orgEntry.Key)
-                    .Contains(entry.Value.OrganizationId));
-            var orgNumberOne = orgCache
-                .Where(orgEntry => orgEntry.Value.Name == "Org_1")
-                .Select(orgEntry => orgEntry.Key)
-                .First();
-            var subSelectCheckCount = cache.Count(entry => entry.Value.OrganizationId == orgNumberOne);
-            Assert.AreEqual(subSelectCheckCount, subSelectCount, "subselecting another CacheQueryable failed");
-
-            var ex = Assert.Throws<NotSupportedException>(() =>
-                CompiledQuery.Compile((int[] k) => cache.Where(x => k.Contains(x.Key))));
-            Assert.AreEqual("'Contains' clause on compiled query parameter is not supported.", ex.Message);
-
-            // check subquery from another cache put in separate variable
-            var orgIds = orgCache
-                .Where(o => o.Value.Name == "Org_1")
-                .Select(o => o.Key);
-
-            var subQueryFromVar = cache
-                .Where(x => orgIds.Contains(x.Value.OrganizationId))
-                .ToArray();
-
-            var subQueryInline = cache
-                .Where(x => orgCache.Where(o => o.Value.Name == "Org_1")
-                    .Select(o => o.Key).Contains(x.Value.OrganizationId))
-                .ToArray();
-
-            Assert.AreEqual(subQueryInline.Length, subQueryFromVar.Length);
-        }
-
-        /// <summary>
-        /// Tests nulls.
-        /// </summary>
-        [Test]
-        public void TestNulls()
-        {
-            var roles = GetRoleCache().AsCacheQueryable();
-
-            var nullNameRole = roles.Single(x => x.Value.Name == null);
-            Assert.AreEqual(null, nullNameRole.Value.Name);
-
-            var nonNullNameRoles = roles.Where(x => x.Value.Name != null);
-            Assert.AreEqual(RoleCount - 1, nonNullNameRoles.Count());
-        }
-
-        /// <summary>
-        /// Tests date time.
-        /// </summary>
-        [Test]
-        public void TestDateTime()
-        {
-            var roles = GetRoleCache().AsCacheQueryable();
-            var persons = GetPersonCache().AsCacheQueryable();
-
-            // Invalid dateTime
-            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
-            var ex = Assert.Throws<BinaryObjectException>(() =>
-                roles.Where(x => x.Value.Date > DateTime.Now).ToArray());
-            Assert.AreEqual("DateTime is not UTC. Only UTC DateTime can be used for interop with other platforms.", 
-                ex.Message);
-
-            // Test retrieval
-            var dates = roles.OrderBy(x => x.Value.Date).Select(x => x.Value.Date);
-            var expDates = GetRoleCache().Select(x => x.Value.Date).OrderBy(x => x).ToArray();
-            Assert.AreEqual(expDates, dates.ToArray());
-
-            // Filtering
-            Assert.AreEqual(1, persons.Count(x => x.Value.Birthday == StartDateTime));
-            Assert.AreEqual(PersonCount, persons.Count(x => x.Value.Birthday >= StartDateTime));
-            Assert.Greater(persons.Count(x => x.Value.Birthday > DateTime.UtcNow), 1);
-
-            // Joins
-            var join = 
-                from role in roles
-                join person in persons on role.Value.Date equals person.Value.Birthday
-                select person;
-
-            Assert.AreEqual(2, join.Count());
-
-            // Functions
-            var strings = dates.Select(x => x.ToString("dd MM YYYY HH:mm:ss")).ToArray();
-            Assert.AreEqual(new[] {"17 05 2000 15:04:05", "29 12 2000 23:04:05", "17 05 2001 15:04:05"}, strings);
-
-            // Properties
-            Assert.AreEqual(new[] {2000, 2000, 2001}, dates.Select(x => x.Year).ToArray());
-            Assert.AreEqual(new[] {5, 12, 5}, dates.Select(x => x.Month).ToArray());
-            Assert.AreEqual(new[] {17, 29, 17}, dates.Select(x => x.Day).ToArray());
-            Assert.AreEqual(expDates.Select(x => x.DayOfYear).ToArray(), dates.Select(x => x.DayOfYear).ToArray());
-            Assert.AreEqual(expDates.Select(x => x.DayOfWeek).ToArray(), dates.Select(x => x.DayOfWeek).ToArray());
-            Assert.AreEqual(new[] {15, 23, 15}, dates.Select(x => x.Hour).ToArray());
-            Assert.AreEqual(new[] { 4, 4, 4 }, dates.Select(x => x.Minute).ToArray());
-            Assert.AreEqual(new[] { 5, 5, 5 }, dates.Select(x => x.Second).ToArray());
-        }
-
-        /// <summary>
-        /// Tests numerics.
-        /// </summary>
-        [Test]
-        public void TestNumerics()
-        {
-            var cache = Ignition.GetIgnite()
-                    .GetOrCreateCache<int, Numerics>(new CacheConfiguration("numerics", typeof (Numerics))
-                {
-                    SqlEscapeAll = GetSqlEscapeAll()
-                });
-
-            for (var i = 0; i < 100; i++)
-                cache[i] = new Numerics(((double) i - 50)/3);
-
-            var query = cache.AsCacheQueryable().Select(x => x.Value);
-
-            var bytes = query.Select(x => x.Byte);
-            var sbytes = query.Select(x => x.Sbyte);
-            var shorts = query.Select(x => x.Short);
-            var ushorts = query.Select(x => x.Ushort);
-            var ints = query.Select(x => x.Int);
-            var uints = query.Select(x => x.Uint);
-            var longs = query.Select(x => x.Long);
-            var ulongs = query.Select(x => x.Ulong);
-            var doubles = query.Select(x => x.Double);
-            var decimals = query.Select(x => x.Decimal);
-            var floats = query.Select(x => x.Float);
-
-            CheckFunc(x => Math.Abs(x), doubles);
-            CheckFunc(x => Math.Abs((sbyte) x), bytes);
-            CheckFunc(x => Math.Abs(x), sbytes);
-            CheckFunc(x => Math.Abs(x), shorts);
-            CheckFunc(x => Math.Abs((short) x), ushorts);
-            CheckFunc(x => Math.Abs(x), ints);
-            CheckFunc(x => Math.Abs((int) x), uints);
-            CheckFunc(x => Math.Abs(x), longs);
-            CheckFunc(x => Math.Abs((long) x), ulongs);
-            CheckFunc(x => Math.Abs(x), decimals);
-            CheckFunc(x => Math.Abs(x), floats);
-
-            CheckFunc(x => Math.Acos(x), doubles);
-            CheckFunc(x => Math.Asin(x), doubles);
-            CheckFunc(x => Math.Atan(x), doubles);
-            CheckFunc(x => Math.Atan2(x, 0.5), doubles);
-
-            CheckFunc(x => Math.Ceiling(x), doubles);
-            CheckFunc(x => Math.Ceiling(x), decimals);
-
-            CheckFunc(x => Math.Cos(x), doubles);
-            CheckFunc(x => Math.Cosh(x), doubles);
-            CheckFunc(x => Math.Exp(x), doubles);
-
-            CheckFunc(x => Math.Floor(x), doubles);
-            CheckFunc(x => Math.Floor(x), decimals);
-
-            CheckFunc(x => Math.Log(x), doubles);
-            CheckFunc(x => Math.Log10(x), doubles);
-
-            CheckFunc(x => Math.Pow(x, 3.7), doubles);
-
-            CheckFunc(x => Math.Round(x), doubles);
-            CheckFunc(x => Math.Round(x, 3), doubles);
-            CheckFunc(x => Math.Round(x), decimals);
-            CheckFunc(x => Math.Round(x, 3), decimals);
-
-            CheckFunc(x => Math.Sign(x), doubles);
-            CheckFunc(x => Math.Sign(x), decimals);
-            CheckFunc(x => Math.Sign(x), floats);
-            CheckFunc(x => Math.Sign(x), ints);
-            CheckFunc(x => Math.Sign(x), longs);
-            CheckFunc(x => Math.Sign(x), shorts);
-            CheckFunc(x => Math.Sign(x), sbytes);
-
-            CheckFunc(x => Math.Sin(x), doubles);
-            CheckFunc(x => Math.Sinh(x), doubles);
-            CheckFunc(x => Math.Sqrt(x), doubles);
-            CheckFunc(x => Math.Tan(x), doubles);
-            CheckFunc(x => Math.Tanh(x), doubles);
-
-            CheckFunc(x => Math.Truncate(x), doubles);
-            CheckFunc(x => Math.Truncate(x), decimals);
-
-            // Operators
-            CheckFunc(x => x*7, doubles);
-            CheckFunc(x => x/7, doubles);
-            CheckFunc(x => x%7, doubles);
-            CheckFunc(x => x+7, doubles);
-            CheckFunc(x => x-7, doubles);
-        }
-
-        /// <summary>
-        /// Tests aliases.
-        /// </summary>
-        [Test]
-        public void TestAliases()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-
-            var res = cache.Where(x => x.Key == 1)
-                .Select(x => new {X = x.Value.AliasTest, Y = x.Value.Address.AliasTest})
-                .Single();
-
-            Assert.AreEqual(new {X = -1, Y = 1}, res);
-        }
-
-        /// <summary>
-        /// Tests the compiled query with various constructs.
-        /// </summary>
-        [Test]
-        public void TestCompiledQuery()
-        {
-            var persons = GetPersonCache().AsCacheQueryable();
-            var roles = GetRoleCache().AsCacheQueryable();
-
-            // Embedded args
-            var qry0 = CompiledQuery.Compile(() => persons.Where(x => x.Key < 3 && x.Value.Name.Contains("son")));
-            Assert.AreEqual(3, qry0().Count());
-
-            // Lambda args
-            var qry1 = CompiledQuery.Compile((int minKey, int take, int skip) => persons.Where(x => x.Key > minKey)
-                .Take(take).Skip(skip));
-            Assert.AreEqual(3, qry1(-1, 3, 1).GetAll().Count);
-
-            qry1 = CompiledQuery.Compile((int skip, int take, int minKey) => persons.Where(x => x.Key > minKey)
-                .Take(take).Skip(skip));
-
-            Assert.AreEqual(5, qry1(2, 5, 20).GetAll().Count);
-
-            // Mixed args
-            var qry2 = CompiledQuery.Compile((int maxKey, int minKey) =>
-                persons.Where(x => x.Key < maxKey
-                                   && x.Value.Name.Contains("er")
-                                   && x.Value.Age < maxKey
-                                   && x.Key > minKey).Skip(2));
-
-            Assert.AreEqual(6, qry2(10, 1).Count());
-
-            // Join
-            var qry3 = CompiledQuery.Compile(() =>
-                roles.Join(persons, r => r.Key.Foo, p => p.Key, (r, p) => r.Value.Name));
-
-            Assert.AreEqual(RoleCount, qry3().Count());
-
-            // Join with subquery
-            var qry4 = CompiledQuery.Compile(
-                (int a, int b, string sep) =>
-                    roles
-                        .Where(x => x.Key.Bar > a)
-                        .OrderBy(x => x.Key.Bar)
-                        .Join(persons.Where(x => x.Key < b && x.Key > 0),
-                            r => r.Key.Foo,
-                            p => p.Value.Address.Zip,
-                            (r, p) => p.Value.Name + sep + r.Value.Name + "|")
-                        .Skip(a).Take(1000)
-                );
-
-            Assert.AreEqual(new[] { " Person_2  =Role_2|", " Person_3  =|"}, qry4(1, PersonCount, "=").ToArray());
-
-            // Union
-            var qry5 = CompiledQuery.Compile(() => roles.Select(x => -x.Key.Foo).Union(persons.Select(x => x.Key)));
-
-            Assert.AreEqual(RoleCount + PersonCount, qry5().Count());
-
-            // Projection
-            var qry6 = CompiledQuery.Compile((int minAge) => persons
-                .Select(x => x.Value)
-                .Where(x => x.Age >= minAge)
-                .Select(x => new { x.Name, x.Age })
-                .OrderBy(x => x.Name));
-
-            var res = qry6(PersonCount - 3).GetAll();
-
-            Assert.AreEqual(3, res.Count);
-            Assert.AreEqual(PersonCount - 3, res[0].Age);
-        }
-
-        /// <summary>
-        /// Tests the compiled query overloads.
-        /// </summary>
-        [Test]
-        public void TestCompiledQueryOverloads()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-
-            // const args are allowed
-            Assert.AreEqual(5, CompiledQuery.Compile(() => cache.Where(x => x.Key < 5))().GetAll().Count);
-
-            // 0 arg
-            var qry0 = CompiledQuery.Compile(() => cache.Select(x => x.Value.Name));
-            Assert.AreEqual(PersonCount, qry0().ToArray().Length);
-
-            // 1 arg
-            var qry1 = CompiledQuery.Compile((int k) => cache.Where(x => x.Key < k));
-            Assert.AreEqual(3, qry1(3).ToArray().Length);
-
-            // 1 arg twice
-            var qry1T = CompiledQuery.Compile((int k) => cache.Where(x => x.Key < k && x.Value.Age < k));
-            Assert.AreEqual(3, qry1T(3).ToArray().Length);
-
-            // 2 arg
-            var qry2 =
-                CompiledQuery.Compile((int i, string s) => cache.Where(x => x.Key < i && x.Value.Name.StartsWith(s)));
-            Assert.AreEqual(5, qry2(5, " Pe").ToArray().Length);
-
-            // Changed param order
-            var qry2R =
-                CompiledQuery.Compile((string s, int i) => cache.Where(x => x.Key < i && x.Value.Name.StartsWith(s)));
-            Assert.AreEqual(5, qry2R(" Pe", 5).ToArray().Length);
-
-            // 3 arg
-            var qry3 = CompiledQuery.Compile((int i, string s, double d) =>
-                cache.Where(x => x.Value.Address.Zip > d && x.Key < i && x.Value.Name.Contains(s)));
-            Assert.AreEqual(5, qry3(5, "son", -10).ToArray().Length);
-
-            // 4 arg
-            var qry4 = CompiledQuery.Compile((int a, int b, int c, int d) =>
-                cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d));
-            Assert.AreEqual(new[] {3, 4}, qry4(0, 1, 2, 5).ToArray());
-
-            // 5 arg
-            var qry5 = CompiledQuery.Compile((int a, int b, int c, int d, int e) =>
-                cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e));
-            Assert.AreEqual(new[] {3, 4}, qry5(0, 1, 2, 5, 6).ToArray());
-
-            // 6 arg
-            var qry6 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f) =>
-                cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e && k < f));
-            Assert.AreEqual(new[] {3, 4}, qry6(0, 1, 2, 5, 6, 7).ToArray());
-
-            // 7 arg
-            var qry7 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f, int g) =>
-                cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e && k < f && k < g));
-            Assert.AreEqual(new[] {3, 4}, qry7(0, 1, 2, 5, 6, 7, 8).ToArray());
-
-            // 8 arg
-            var qry8 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f, int g, int h) =>
-                cache.Select(x => x.Key)
-                    .Where(k => k > a && k > b && k > c && k < d && k < e && k < f && k < g && k < h));
-            Assert.AreEqual(new[] {3, 4}, qry8(0, 1, 2, 5, 6, 7, 8, 9).ToArray());
-        }
-
-        /// <summary>
-        /// Tests the free-form compiled query, where user provides an array of arguments.
-        /// </summary>
-        [Test]
-        public void TestCompiledQueryFreeform()
-        {
-            var cache = GetPersonCache().AsCacheQueryable();
-
-            var qry = cache.Where(x => x.Key < 5);
-
-            // Simple
-            var compiled = CompiledQuery.Compile(qry);
-
-            Assert.AreEqual(5, compiled(5).Count());
-            Assert.AreEqual(6, compiled(6).Count());
-
-            // Select
-            var compiledSelect = CompiledQuery.Compile(qry.Select(x => x.Value.Name).OrderBy(x => x));
-
-            Assert.AreEqual(3, compiledSelect(3).Count());
-            Assert.AreEqual(" Person_0  ", compiledSelect(1).Single());
-
-            // Join
-            var compiledJoin = CompiledQuery.Compile(qry.Join(
-                GetOrgCache().AsCacheQueryable().Where(x => x.Value.Name.StartsWith("Org")),
-                p => p.Value.OrganizationId, o => o.Value.Id, (p, o) => o.Key));
-
-            Assert.AreEqual(1000, compiledJoin("Org", 1).Single());
-
-            // Many parameters
-            var qry2 = cache.Where(x => x.Key < 3)
-                .Where(x => x.Key > 0)
-                .Where(x => x.Value.Name.Contains(""))
-                .Where(x => x.Value.Address.Zip > 0)
-                .Where(x => x.Value.Age == 7);
-
-            var compiled2 = CompiledQuery.Compile(qry2);
-
-            Assert.AreEqual(17, compiled2(18, 16, "ers", 13, 17).Single().Key);
-        }
-
-        /// <summary>
-        /// Tests the cache of primitive types.
-        /// </summary>
-        [Test]
-        public void TestPrimitiveCache()
-        {
-            // Create partitioned cache
-            var cache = Ignition.GetIgnite()
-                .GetOrCreateCache<int, string>(
-                    new CacheConfiguration("primitiveCache",
-                        new QueryEntity(typeof(int), typeof(string)))
-                    {
-                        CacheMode = CacheMode.Replicated,
-                        SqlEscapeAll = GetSqlEscapeAll()
-                    });
-
-            var qry = cache.AsCacheQueryable();
-
-            // Populate
-            const int count = 100;
-            cache.PutAll(Enumerable.Range(0, count).ToDictionary(x => x, x => x.ToString()));
-
-            // Test
-            Assert.AreEqual(count, qry.ToArray().Length);
-            Assert.AreEqual(10, qry.Where(x => x.Key < 10).ToArray().Length);
-            Assert.AreEqual(1, qry.Count(x => x.Value.Contains("99")));
-        }
-
-        /// <summary>
-        /// Tests the local query.
-        /// </summary>
-        [Test]
-        public void TestLocalQuery()
-        {
-            // Create partitioned cache
-            var cache =
-                Ignition.GetIgnite().GetOrCreateCache<int, int>(new CacheConfiguration("partCache", typeof (int))
-                {
-                    SqlEscapeAll = GetSqlEscapeAll()
-                });
-
-            // Populate
-            const int count = 100;
-            cache.PutAll(Enumerable.Range(0, count).ToDictionary(x => x, x => x));
-
-            // Non-local query returns all records
-            Assert.AreEqual(count, cache.AsCacheQueryable(false).ToArray().Length);
-
-            // Local query returns only some of the records
-            var localCount = cache.AsCacheQueryable(true).ToArray().Length;
-            Assert.Less(localCount, count);
-            Assert.Greater(localCount, 0);
-        }
-
-        /// <summary>
-        /// Tests the introspection.
-        /// </summary>
-        [Test]
-        public void TestIntrospection()
-        {
-            var cache = GetPersonCache();
-
-            // Check regular query
-            var query = cache.AsCacheQueryable(new QueryOptions
-            {
-                Local = true,
-                PageSize = 999,
-                EnforceJoinOrder = true,
-                Timeout = TimeSpan.FromSeconds(2.5),
-                ReplicatedOnly = true,
-                Colocated = true
-            }).Where(x => x.Key > 10).ToCacheQueryable();
-
-            Assert.AreEqual(cache.Name, query.CacheName);
-            Assert.AreEqual(cache.Ignite, query.Ignite);
-
-            var fq = query.GetFieldsQuery();
-
-            Assert.AreEqual(
-                GetSqlEscapeAll()
-                    ? "select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where (_T0.\"_KEY\" > ?)"
-                    : "select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where (_T0._KEY > ?)",
-                fq.Sql);
-
-            Assert.AreEqual(new[] {10}, fq.Arguments);
-            Assert.IsTrue(fq.Local);
-            Assert.AreEqual(PersonCount - 11, cache.QueryFields(fq).GetAll().Count);
-            Assert.AreEqual(999, fq.PageSize);
-            Assert.IsFalse(fq.EnableDistributedJoins);
-            Assert.IsTrue(fq.EnforceJoinOrder);
-            Assert.IsTrue(fq.ReplicatedOnly);
-            Assert.IsTrue(fq.Colocated);
-            Assert.AreEqual(TimeSpan.FromSeconds(2.5), fq.Timeout);
-
-            var str = query.ToString();
-            Assert.AreEqual(GetSqlEscapeAll()
-                ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
-                  "(_T0.\"_KEY\" > ?), Arguments=[10], " +
-                  "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
-                  "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]"
-                : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
-                  "(_T0._KEY > ?), Arguments=[10], " +
-                  "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
-                  "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]", str);
-
-            // Check fields query
-            var fieldsQuery = (ICacheQueryable) cache.AsCacheQueryable().Select(x => x.Value.Name);
-
-            Assert.AreEqual(cache.Name, fieldsQuery.CacheName);
-            Assert.AreEqual(cache.Ignite, fieldsQuery.Ignite);
-
-            fq = fieldsQuery.GetFieldsQuery();
-            Assert.AreEqual(GetSqlEscapeAll()
-                    ? "select _T0.\"Name\" from \"person_org\".\"Person\" as _T0"
-                    : "select _T0.NAME from \"person_org\".Person as _T0",
-                fq.Sql);
-
-            Assert.IsFalse(fq.Local);
-            Assert.AreEqual(SqlFieldsQuery.DefaultPageSize, fq.PageSize);
-            Assert.IsFalse(fq.EnableDistributedJoins);
-            Assert.IsFalse(fq.EnforceJoinOrder);
-
-            str = fieldsQuery.ToString();
-            Assert.AreEqual(GetSqlEscapeAll()
-                ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0.\"Name\" from \"person_org\".\"Person\" as _T0, Arguments=[], Local=False, " +
-                  "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
-                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
-                : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0.NAME from \"person_org\".Person as _T0, Arguments=[], Local=False, " +
-                  "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
-                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
-            
-            // Check distributed joins flag propagation
-            var distrQuery = cache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true})
-                .Where(x => x.Key > 10 && x.Value.Age > 20 && x.Value.Name.Contains("x"));
-
-            query = distrQuery.ToCacheQueryable();
-
-            Assert.IsTrue(query.GetFieldsQuery().EnableDistributedJoins);
-
-            str = distrQuery.ToString();
-            Assert.AreEqual(GetSqlEscapeAll()
-                ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
-                  "(((_T0.\"_KEY\" > ?) and (_T0.\"age1\" > ?)) " +
-                  "and (_T0.\"Name\" like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
-                  "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
-                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
-                : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
-                  "(((_T0._KEY > ?) and (_T0.AGE1 > ?)) " +
-                  "and (_T0.NAME like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
-                  "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
-                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
-        }
-
-        /// <summary>
-        /// Tests the table name inference.
-        /// </summary>
-        [Test]
-        public void TestTableNameInference()
-        {
-            // Try with multi-type cache: explicit type is required
-            var cache = GetCacheOf<IPerson>();
-
-            Assert.Throws<CacheException>(() => cache.AsCacheQueryable());
-
-            var names = cache.AsCacheQueryable(false, "Person").Select(x => x.Value.Name).ToArray();
-
-            Assert.AreEqual(PersonCount, names.Length);
-
-            // With single-type cache, interface inference works
-            var roleCache = Ignition.GetIgnite().GetCache<object, IRole>(RoleCacheName).AsCacheQueryable();
-
-            var roleNames = roleCache.Select(x => x.Value.Name).OrderBy(x => x).ToArray();
-
-            CollectionAssert.AreEquivalent(new[] {"Role_1", "Role_2", null}, roleNames);
-
-            // Check non-queryable cache
-            var nonQueryableCache = Ignition.GetIgnite().GetOrCreateCache<Role, Person>("nonQueryable");
-
-            Assert.Throws<CacheException>(() => nonQueryableCache.AsCacheQueryable());
-        }
-
-        /// <summary>
-        /// Tests the distributed joins.
-        /// </summary>
-        [Test]
-        public void TestDistributedJoins()
-        {
-            var ignite = Ignition.GetIgnite();
-
-            // Create and populate partitioned caches
-            var personCache = ignite.CreateCache<int, Person>(new CacheConfiguration("partitioned_persons",
-                new QueryEntity(typeof(int), typeof(Person)))
-            {
-                SqlEscapeAll = GetSqlEscapeAll()
-            });
-
-            personCache.PutAll(GetSecondPersonCache().ToDictionary(x => x.Key, x => x.Value));
-
-            var roleCache = ignite.CreateCache<int, Role>(new CacheConfiguration("partitioned_roles",
-                    new QueryEntity(typeof(int), typeof(Role)))
-            {
-                SqlEscapeAll = GetSqlEscapeAll()
-            });
-
-            roleCache.PutAll(GetRoleCache().ToDictionary(x => x.Key.Foo, x => x.Value));
-
-            // Test non-distributed join: returns partial results
-            var persons = personCache.AsCacheQueryable();
-            var roles = roleCache.AsCacheQueryable();
-
-            var res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
-                .ToArray();
-
-            Assert.AreEqual(res.Length, RoleCount);
-
-            // Test distributed join: returns complete results
-            persons = personCache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true});
-            roles = roleCache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true});
-
-            res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
-                .ToArray();
-
-            Assert.AreEqual(RoleCount, res.Length);
-        }
-
-        /// <summary>
-        /// Tests the query timeout.
-        /// </summary>
-        [Test]
-        public void TestTimeout()
-        {
-            var persons = GetPersonCache().AsCacheQueryable(new QueryOptions
-            {
-                Timeout = TimeSpan.FromMilliseconds(1),
-                EnableDistributedJoins = true
-            });
-
-            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
-            var ex = Assert.Throws<CacheException>(() =>
-                persons.SelectMany(p => GetRoleCache().AsCacheQueryable()).ToArray());
-
-            Assert.IsTrue(ex.ToString().Contains("QueryCancelledException: The query was cancelled while executing."));
-        }
-
-        /// <summary>
-        /// Tests the RemoveAll extension.
-        /// </summary>
-        [Test]
-        public void TestRemoveAll()
-        {
-            // Use new cache to avoid touching static data.
-            var cache = Ignition.GetIgnite().CreateCache<int, Person>(new CacheConfiguration("deleteAllTest",
-                    new QueryEntity(typeof(int), typeof(Person)))
-            {
-                SqlEscapeAll = GetSqlEscapeAll()
-            });
-
-            Enumerable.Range(1, 10).ToList().ForEach(x => cache.Put(x, new Person(x, x.ToString())));
-            
-            var queryable = cache.AsCacheQueryable();
-
-            Func<int[]> getKeys = () => cache.Select(x => x.Key).OrderBy(x => x).ToArray();
-
-            // Without predicate.
-            var res = queryable.Where(x => x.Key < 3).RemoveAll();
-            Assert.AreEqual(2, res);
-            Assert.AreEqual(Enumerable.Range(3, 8), getKeys());
-
-            // With predicate.
-            res = queryable.RemoveAll(x => x.Key < 7);
-            Assert.AreEqual(4, res);
-            Assert.AreEqual(Enumerable.Range(7, 4), getKeys());
-
-            // Subquery-style join.
-            var ids = GetPersonCache().AsCacheQueryable().Where(x => x.Key == 7).Select(x => x.Key);
-
-            res = queryable.Where(x => ids.Contains(x.Key)).RemoveAll();
-            Assert.AreEqual(1, res);
-            Assert.AreEqual(Enumerable.Range(8, 3), getKeys());
-
-            // Row number limit.
-            res = queryable.Take(2).RemoveAll();
-            Assert.AreEqual(2, res);
-            Assert.AreEqual(1, getKeys().Length);
-
-            // Unconditional.
-            queryable.RemoveAll();
-            Assert.AreEqual(0, cache.GetSize());
-
-            // Skip is not supported with DELETE.
-            var nex = Assert.Throws<NotSupportedException>(() => queryable.Skip(1).RemoveAll());
-            Assert.AreEqual(
-                "RemoveAll can not be combined with result operators (other than Take): SkipResultOperator",
-                nex.Message);
-
-            // Multiple result operators are not supported with DELETE.
-            nex = Assert.Throws<NotSupportedException>(() => queryable.Skip(1).Take(1).RemoveAll());
-            Assert.AreEqual(
-                "RemoveAll can not be combined with result operators (other than Take): SkipResultOperator, " +
-                "TakeResultOperator, RemoveAllResultOperator", nex.Message);
-
-            // Joins are not supported in H2.
-            var qry = queryable
-                .Where(x => x.Key == 7)
-                .Join(GetPersonCache().AsCacheQueryable(), p => p.Key, p => p.Key, (p1, p2) => p1);
-
-            var ex = Assert.Throws<IgniteException>(() => qry.RemoveAll());
-            Assert.AreEqual("Failed to parse query", ex.Message.Substring(0, 21));
-        }
-
-        /// <summary>
-        /// Gets the person cache.
-        /// </summary>
-        /// <returns></returns>
-        private ICache<int, Person> GetPersonCache()
-        {
-            return GetCacheOf<Person>();
-        }
-
-        /// <summary>
-        /// Gets the org cache.
-        /// </summary>
-        /// <returns></returns>
-        private ICache<int, Organization> GetOrgCache()
-        {
-            return GetCacheOf<Organization>();
-        }
-
-        /// <summary>
-        /// Gets the cache.
-        /// </summary>
-        private ICache<int, T> GetCacheOf<T>()
-        {
-            return Ignition.GetIgnite()
-                .GetOrCreateCache<int, T>(new CacheConfiguration(PersonOrgCacheName,
-                    new QueryEntity(typeof (int), typeof (Person))
-                    {
-                        Aliases = new[]
-                        {
-                            new QueryAlias("AliasTest", "Person_AliasTest"),
-                            new QueryAlias("Address.AliasTest", "Addr_AliasTest")
-                        },
-                        KeyFieldName = "MyKey",
-                        ValueFieldName = "MyValue",
-                        Fields =
-                        {
-                            new QueryField("MyKey", typeof(int)),
-                            new QueryField("MyValue", typeof(T)),
-                        }
-                    },
-                    new QueryEntity(typeof (int), typeof (Organization)))
-                {
-                    CacheMode = CacheMode.Replicated,
-                    SqlEscapeAll = GetSqlEscapeAll()
-                });
-        }
-
-        /// <summary>
-        /// Gets the role cache.
-        /// </summary>
-        private ICache<RoleKey, Role> GetRoleCache()
-        {
-            return Ignition.GetIgnite()
-                .GetOrCreateCache<RoleKey, Role>(new CacheConfiguration(RoleCacheName,
-                    new QueryEntity(typeof (RoleKey), typeof (Role)))
-                {
-                    CacheMode = CacheMode.Replicated,
-                    SqlEscapeAll = GetSqlEscapeAll()
-                });
-        }
-
-        /// <summary>
-        /// Gets the second person cache.
-        /// </summary>
-        private ICache<int, Person> GetSecondPersonCache()
-        {
-            return Ignition.GetIgnite()
-                .GetOrCreateCache<int, Person>(
-                    new CacheConfiguration(PersonSecondCacheName,
-                        new QueryEntity(typeof(int), typeof(Person))
-                        {
-                            TableName = "CustomPersons"
-                        })
-                    {
-                        CacheMode = CacheMode.Replicated,
-                        SqlEscapeAll = GetSqlEscapeAll()
-                    });
-        }
-
-        /// <summary>
-        /// Checks that function maps to SQL function properly.
-        /// </summary>
-        private static void CheckFunc<T, TR>(Expression<Func<T, TR>> exp, IQueryable<T> query, 
-            Func<TR, TR> localResultFunc = null)
-        {
-            localResultFunc = localResultFunc ?? (x => x);
-
-            // Calculate result locally, using real method invocation
-            var expected = query.ToArray().AsQueryable().Select(exp).Select(localResultFunc).OrderBy(x => x).ToArray();
-
-            // Perform SQL query
-            var actual = query.Select(exp).ToArray().OrderBy(x => x).ToArray();
-
-            // Compare results
-            CollectionAssert.AreEqual(expected, actual, new NumericComparer());
-
-            // Perform intermediate anonymous type conversion to check type projection
-            actual = query.Select(exp).Select(x => new {Foo = x}).ToArray().Select(x => x.Foo)
-                .OrderBy(x => x).ToArray();
-
-            // Compare results
-            CollectionAssert.AreEqual(expected, actual, new NumericComparer());
-        }
-
-        /// <summary>
-        /// Checks that function used in Where Clause maps to SQL function properly
-        /// </summary>
-        private static void CheckWhereFunc<TKey, TEntry>(IQueryable<ICacheEntry<TKey,TEntry>> query, 
-            Expression<Func<ICacheEntry<TKey, TEntry>,bool>> whereExpression)
-        {
-            // Calculate result locally, using real method invocation
-            var expected = query
-                .ToArray()
-                .AsQueryable()
-                .Where(whereExpression)
-                .Select(entry => entry.Key)
-                .OrderBy(x => x)
-                .ToArray();
-
-            // Perform SQL query
-            var actual = query
-                .Where(whereExpression)
-                .Select(entry => entry.Key)
-                .ToArray()
-                .OrderBy(x => x)
-                .ToArray();
-
-            // Compare results
-            CollectionAssert.AreEqual(expected, actual, new NumericComparer());
-        }
-
-        /// <summary>
-        /// Tests conditinal statement
-        /// </summary>
-        private void TestConditional<T>(T even , T odd, Func<T,T,bool> comparer = null)
-        {
-            var persons = GetPersonCache().AsCacheQueryable();
-
-            var res = persons
-                .Select(x => new {Foo = x.Key % 2 == 0 ? even : odd, x.Value})
-                .ToArray();
-
-            if (comparer != null)
-            {
-                Assert.IsTrue(comparer(even, res[0].Foo));
-                Assert.IsTrue(comparer(odd, res[1].Foo));
-            }
-            else
-            {
-                Assert.AreEqual(even, res[0].Foo);
-                Assert.AreEqual(odd, res[1].Foo);
-            }
-        }
-
-        /// <summary>
-        /// Tests conditinal statement for structs with default and null values
-        /// </summary>
-        private void TestConditionalWithNullableStructs<T>(T? defaultFalue = null) where T : struct
-        {
-            var def = defaultFalue ?? default(T);
-            TestConditional(def, (T?) null);
-        }
-
-        public interface IPerson
-        {
-            int Age { get; set; }
-            string Name { get; set; }
-        }
-
-        public class Person : IBinarizable, IPerson
-        {
-            public Person(int age, string name)
-            {
-                Age = age;
-                Name = name;
-            }
-
-            [QuerySqlField(Name = "age1")] public int Age { get; set; }
-
-            [QuerySqlField] public string Name { get; set; }
-
-            [QuerySqlField] public Address Address { get; set; }
-
-            [QuerySqlField] public int OrganizationId { get; set; }
-
-            [QuerySqlField] public DateTime? Birthday { get; set; }
-
-            [QuerySqlField] public int AliasTest { get; set; }
-
-            public void WriteBinary(IBinaryWriter writer)
-            {
-                writer.WriteInt("age1", Age);
-                writer.WriteString("name", Name);
-                writer.WriteInt("OrganizationId", OrganizationId);
-                writer.WriteObject("Address", Address);
-                writer.WriteTimestamp("Birthday", Birthday);
-                writer.WriteInt("AliasTest", AliasTest);
-            }
-
-            public void ReadBinary(IBinaryReader reader)
-            {
-                Age = reader.ReadInt("age1");
-                Name = reader.ReadString("name");
-                OrganizationId = reader.ReadInt("OrganizationId");
-                Address = reader.ReadObject<Address>("Address");
-                Birthday = reader.ReadTimestamp("Birthday");
-                AliasTest = reader.ReadInt("AliasTest");
-            }
-        }
-
-        public class Address
-        {
-            [QuerySqlField] public int Zip { get; set; }
-            [QuerySqlField] public string Street { get; set; }
-            [QuerySqlField] public int AliasTest { get; set; }
-        }
-
-        public class Organization
-        {
-            [QuerySqlField] public int Id { get; set; }
-            [QuerySqlField] public string Name { get; set; }
-        }
-
-        public interface IRole
-        {
-            string Name { get; }
-            DateTime Date { get; }
-        }
-
-        public class Role : IRole
-        {
-            [QuerySqlField] public string Name { get; set; }
-            [QuerySqlField] public DateTime Date { get; set; }
-        }
-
-        public class Numerics
-        {
-            public Numerics(double val)
-            {
-                Double = val;
-                Float = (float) val;
-                Decimal = (decimal) val;
-                Int = (int) val;
-                Uint = (uint) val;
-                Long = (long) val;
-                Ulong = (ulong) val;
-                Short = (short) val;
-                Ushort = (ushort) val;
-                Byte = (byte) val;
-                Sbyte =  (sbyte) val;
-            }
-
-            [QuerySqlField] public double Double { get; set; }
-            [QuerySqlField] public float Float { get; set; }
-            [QuerySqlField] public decimal Decimal { get; set; }
-            [QuerySqlField] public int Int { get; set; }
-            [QuerySqlField] public uint Uint { get; set; }
-            [QuerySqlField] public long Long { get; set; }
-            [QuerySqlField] public ulong Ulong { get; set; }
-            [QuerySqlField] public short Short { get; set; }
-            [QuerySqlField] public ushort Ushort { get; set; }
-            [QuerySqlField] public byte Byte { get; set; }
-            [QuerySqlField] public sbyte Sbyte { get; set; }
-        }
-
-        public struct RoleKey : IEquatable<RoleKey>
-        {
-            private readonly int _foo;
-            private readonly long _bar;
-
-            public RoleKey(int foo, long bar)
-            {
-                _foo = foo;
-                _bar = bar;
-            }
-
-            [QuerySqlField(Name = "_foo")]
-            public int Foo
-            {
-                get { return _foo; }
-            }
-
-            [QuerySqlField(Name = "_bar")]
-            public long Bar
-            {
-                get { return _bar; }
-            }
-
-            public bool Equals(RoleKey other)
-            {
-                return _foo == other._foo && _bar == other._bar;
-            }
-
-            public override bool Equals(object obj)
-            {
-                if (ReferenceEquals(null, obj)) return false;
-                return obj is RoleKey && Equals((RoleKey) obj);
-            }
-
-            public override int GetHashCode()
-            {
-                unchecked
-                {
-                    return (_foo*397) ^ _bar.GetHashCode();
-                }
-            }
-
-            public static bool operator ==(RoleKey left, RoleKey right)
-            {
-                return left.Equals(right);
-            }
-
-            public static bool operator !=(RoleKey left, RoleKey right)
-            {
-                return !left.Equals(right);
-            }
-        }
-
-        /// <summary>
-        /// Epsilon comparer.
-        /// </summary>
-        private class NumericComparer : IComparer
-        {
-            /** <inheritdoc /> */
-            public int Compare(object x, object y)
-            {
-                if (Equals(x, y))
-                    return 0;
-
-                if (x is double)
-                {
-                    var dx = (double) x;
-                    var dy = (double) y;
-
-                    // Epsilon is proportional to the min value, but not too small.
-                    const double epsilon = 2E-10d;
-                    var min = Math.Min(Math.Abs(dx), Math.Abs(dy));
-                    var relEpsilon = Math.Max(min*epsilon, epsilon);
-
-                    // Compare with epsilon because some funcs return slightly different results.
-                    return Math.Abs((double) x - (double) y) < relEpsilon ? 0 : 1;
-                }
-
-                return ((IComparable) x).CompareTo(y);
-            }
-        }
-    }
-}


[2/3] ignite git commit: IGNITE-5532 .NET: Split CacheLinqTest into partial classes

Posted by pt...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSimpleName.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSimpleName.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSimpleName.cs
deleted file mode 100644
index 9743e60..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSimpleName.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace Apache.Ignite.Core.Tests.Cache.Query
-{
-    using Apache.Ignite.Core.Binary;
-    using NUnit.Framework;
-
-    /// <summary>
-    /// LINQ test with simple name mapper.
-    /// </summary>
-    [TestFixture]
-    public class CacheLinqTestSimpleName : CacheLinqTest
-    {
-        /** <inheritdoc /> */
-        protected override IBinaryNameMapper GetNameMapper()
-        {
-            return BinaryBasicNameMapper.SimpleNameInstance;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSqlEscapeAll.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSqlEscapeAll.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSqlEscapeAll.cs
deleted file mode 100644
index 7473be9..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSqlEscapeAll.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace Apache.Ignite.Core.Tests.Cache.Query
-{
-    using NUnit.Framework;
-
-    /// <summary>
-    /// LINQ test with simple name mapper.
-    /// </summary>
-    [TestFixture]
-    public class CacheLinqTestSqlEscapeAll : CacheLinqTest
-    {
-        /** <inheritdoc /> */
-        protected override bool GetSqlEscapeAll()
-        {
-            return true;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Aggregates.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Aggregates.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Aggregates.cs
new file mode 100644
index 0000000..b6bbb67
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Aggregates.cs
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Linq;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests aggregates.
+        /// </summary>
+        [Test]
+        public void TestAggregates()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+
+            Assert.AreEqual(PersonCount, cache.Count());
+            Assert.AreEqual(PersonCount, cache.Select(x => x.Key).Count());
+            Assert.AreEqual(2, cache.Select(x => x.Value.OrganizationId).Distinct().Count());
+
+            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+            Assert.Throws<NotSupportedException>(() => cache.Select(x => new { x.Key, x.Value }).Count());
+
+            // Min/max/sum/avg
+            var ints = cache.Select(x => x.Key);
+            Assert.AreEqual(0, ints.Min());
+            Assert.AreEqual(PersonCount - 1, ints.Max());
+            Assert.AreEqual(ints.ToArray().Sum(), ints.Sum());
+            Assert.AreEqual((int)ints.ToArray().Average(), (int)ints.Average());
+
+            var dupInts = ints.Select(x => x / 10);  // duplicate values
+            CollectionAssert.AreEquivalent(dupInts.ToArray().Distinct().ToArray(), dupInts.Distinct().ToArray());
+            Assert.AreEqual(dupInts.ToArray().Distinct().Sum(), dupInts.Distinct().Sum());
+
+            // All/any
+            Assert.IsFalse(ints.Where(x => x > -5).Any(x => x > PersonCount && x > 0));
+            Assert.IsTrue(ints.Any(x => x < PersonCount / 2));
+
+            // Skip/take
+            var keys = cache.Select(x => x.Key).OrderBy(x => x);
+            Assert.AreEqual(new[] { 0, 1 }, keys.Take(2).ToArray());
+            Assert.AreEqual(new[] { 1, 2 }, keys.Skip(1).Take(2).ToArray());
+            Assert.AreEqual(new[] { PersonCount - 2, PersonCount - 1 }, keys.Skip(PersonCount - 2).ToArray());
+        }
+
+        /// <summary>
+        /// Tests aggregates with all clause.
+        /// </summary>
+        [Test]
+        public void TestAggregatesAll()
+        {
+            var ints = GetPersonCache().AsCacheQueryable().Select(x => x.Key);
+
+            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+            var ex = Assert.Throws<NotSupportedException>(() => ints.Where(x => x > -10)
+                .All(x => x < PersonCount && x >= 0));
+
+            Assert.IsTrue(ex.Message.StartsWith("Operator is not supported: All"));
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
new file mode 100644
index 0000000..ae9fd5f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
@@ -0,0 +1,506 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Collections;
+    using System.Linq;
+    using System.Linq.Expressions;
+    using System.Threading;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /** Cache name. */
+        private const string PersonOrgCacheName = "person_org";
+
+        /** Cache name. */
+        private const string PersonSecondCacheName = "person_cache";
+
+        /** Role cache name. */
+        private const string RoleCacheName = "role_cache";
+
+        /** */
+        private const int RoleCount = 3;
+
+        /** */
+        private const int PersonCount = 900;
+
+        /** */
+        private bool _runDbConsole;
+
+        /** */
+        private static readonly DateTime StartDateTime = new DateTime(2000, 5, 17, 15, 4, 5, DateTimeKind.Utc);
+
+        /// <summary>
+        /// Fixture set up.
+        /// </summary>
+        [TestFixtureSetUp]
+        public void FixtureSetUp()
+        {
+            _runDbConsole = false;  // set to true to open H2 console
+
+            if (_runDbConsole)
+                Environment.SetEnvironmentVariable("IGNITE_H2_DEBUG_CONSOLE", "true");
+
+            Ignition.Start(GetConfig());
+            Ignition.Start(GetConfig("grid2"));
+
+            // Populate caches
+            var cache = GetPersonCache();
+            var personCache = GetSecondPersonCache();
+
+            for (var i = 0; i < PersonCount; i++)
+            {
+                cache.Put(i, new Person(i, string.Format(" Person_{0}  ", i))
+                {
+                    Address = new Address {Zip = i, Street = "Street " + i, AliasTest = i},
+                    OrganizationId = i%2 + 1000,
+                    Birthday = StartDateTime.AddYears(i),
+                    AliasTest = -i
+                });
+
+                var i2 = i + PersonCount;
+                personCache.Put(i2, new Person(i2, "Person_" + i2)
+                {
+                    Address = new Address {Zip = i2, Street = "Street " + i2},
+                    OrganizationId = i%2 + 1000,
+                    Birthday = StartDateTime.AddYears(i)
+                });
+            }
+
+            var orgCache = GetOrgCache();
+
+            orgCache[1000] = new Organization {Id = 1000, Name = "Org_0"};
+            orgCache[1001] = new Organization {Id = 1001, Name = "Org_1"};
+            orgCache[1002] = new Organization {Id = 1002, Name = null};
+
+            var roleCache = GetRoleCache();
+
+            roleCache[new RoleKey(1, 101)] = new Role {Name = "Role_1", Date = StartDateTime};
+            roleCache[new RoleKey(2, 102)] = new Role {Name = "Role_2", Date = StartDateTime.AddYears(1)};
+            roleCache[new RoleKey(3, 103)] = new Role {Name = null, Date = StartDateTime.AddHours(5432)};
+        }
+
+        /// <summary>
+        /// Gets the configuration.
+        /// </summary>
+        private IgniteConfiguration GetConfig(string gridName = null)
+        {
+            return new IgniteConfiguration(TestUtils.GetTestConfiguration())
+            {
+                BinaryConfiguration = new BinaryConfiguration(typeof(Person),
+                    typeof(Organization), typeof(Address), typeof(Role), typeof(RoleKey), typeof(Numerics))
+                {
+                    NameMapper = GetNameMapper()
+                },
+                IgniteInstanceName = gridName
+            };
+        }
+
+        /// <summary>
+        /// Gets the name mapper.
+        /// </summary>
+        protected virtual IBinaryNameMapper GetNameMapper()
+        {
+            return BinaryBasicNameMapper.FullNameInstance;
+        }
+
+        /// <summary>
+        /// Gets the SqlEscapeAll setting.
+        /// </summary>
+        protected virtual bool GetSqlEscapeAll()
+        {
+            return false;
+        }
+
+        /// <summary>
+        /// Fixture tear down.
+        /// </summary>
+        [TestFixtureTearDown]
+        public void FixtureTearDown()
+        {
+            if (_runDbConsole)
+                Thread.Sleep(Timeout.Infinite);
+            Ignition.StopAll(true);
+        }
+
+        /// <summary>
+        /// Gets the person cache.
+        /// </summary>
+        /// <returns></returns>
+        private ICache<int, Person> GetPersonCache()
+        {
+            return GetCacheOf<Person>();
+        }
+
+        /// <summary>
+        /// Gets the org cache.
+        /// </summary>
+        /// <returns></returns>
+        private ICache<int, Organization> GetOrgCache()
+        {
+            return GetCacheOf<Organization>();
+        }
+
+        /// <summary>
+        /// Gets the cache.
+        /// </summary>
+        private ICache<int, T> GetCacheOf<T>()
+        {
+            return Ignition.GetIgnite()
+                .GetOrCreateCache<int, T>(new CacheConfiguration(PersonOrgCacheName,
+                    new QueryEntity(typeof (int), typeof (Person))
+                    {
+                        Aliases = new[]
+                        {
+                            new QueryAlias("AliasTest", "Person_AliasTest"),
+                            new QueryAlias("Address.AliasTest", "Addr_AliasTest")
+                        },
+                        KeyFieldName = "MyKey",
+                        ValueFieldName = "MyValue",
+                        Fields =
+                        {
+                            new QueryField("MyKey", typeof(int)),
+                            new QueryField("MyValue", typeof(T)),
+                        }
+                    },
+                    new QueryEntity(typeof (int), typeof (Organization)))
+                {
+                    CacheMode = CacheMode.Replicated,
+                    SqlEscapeAll = GetSqlEscapeAll()
+                });
+        }
+
+        /// <summary>
+        /// Gets the role cache.
+        /// </summary>
+        private ICache<RoleKey, Role> GetRoleCache()
+        {
+            return Ignition.GetIgnite()
+                .GetOrCreateCache<RoleKey, Role>(new CacheConfiguration(RoleCacheName,
+                    new QueryEntity(typeof (RoleKey), typeof (Role)))
+                {
+                    CacheMode = CacheMode.Replicated,
+                    SqlEscapeAll = GetSqlEscapeAll()
+                });
+        }
+
+        /// <summary>
+        /// Gets the second person cache.
+        /// </summary>
+        private ICache<int, Person> GetSecondPersonCache()
+        {
+            return Ignition.GetIgnite()
+                .GetOrCreateCache<int, Person>(
+                    new CacheConfiguration(PersonSecondCacheName,
+                        new QueryEntity(typeof(int), typeof(Person))
+                        {
+                            TableName = "CustomPersons"
+                        })
+                    {
+                        CacheMode = CacheMode.Replicated,
+                        SqlEscapeAll = GetSqlEscapeAll()
+                    });
+        }
+
+        /// <summary>
+        /// Checks that function maps to SQL function properly.
+        /// </summary>
+        private static void CheckFunc<T, TR>(Expression<Func<T, TR>> exp, IQueryable<T> query, 
+            Func<TR, TR> localResultFunc = null)
+        {
+            localResultFunc = localResultFunc ?? (x => x);
+
+            // Calculate result locally, using real method invocation
+            var expected = query.ToArray().AsQueryable().Select(exp).Select(localResultFunc).OrderBy(x => x).ToArray();
+
+            // Perform SQL query
+            var actual = query.Select(exp).ToArray().OrderBy(x => x).ToArray();
+
+            // Compare results
+            CollectionAssert.AreEqual(expected, actual, new NumericComparer());
+
+            // Perform intermediate anonymous type conversion to check type projection
+            actual = query.Select(exp).Select(x => new {Foo = x}).ToArray().Select(x => x.Foo)
+                .OrderBy(x => x).ToArray();
+
+            // Compare results
+            CollectionAssert.AreEqual(expected, actual, new NumericComparer());
+        }
+
+        /// <summary>
+        /// Checks that function used in Where Clause maps to SQL function properly
+        /// </summary>
+        private static void CheckWhereFunc<TKey, TEntry>(IQueryable<ICacheEntry<TKey,TEntry>> query, 
+            Expression<Func<ICacheEntry<TKey, TEntry>,bool>> whereExpression)
+        {
+            // Calculate result locally, using real method invocation
+            var expected = query
+                .ToArray()
+                .AsQueryable()
+                .Where(whereExpression)
+                .Select(entry => entry.Key)
+                .OrderBy(x => x)
+                .ToArray();
+
+            // Perform SQL query
+            var actual = query
+                .Where(whereExpression)
+                .Select(entry => entry.Key)
+                .ToArray()
+                .OrderBy(x => x)
+                .ToArray();
+
+            // Compare results
+            CollectionAssert.AreEqual(expected, actual, new NumericComparer());
+        }
+
+        /// <summary>
+        /// Tests conditinal statement
+        /// </summary>
+        private void TestConditional<T>(T even , T odd, Func<T,T,bool> comparer = null)
+        {
+            var persons = GetPersonCache().AsCacheQueryable();
+
+            var res = persons
+                .Select(x => new {Foo = x.Key % 2 == 0 ? even : odd, x.Value})
+                .ToArray();
+
+            if (comparer != null)
+            {
+                Assert.IsTrue(comparer(even, res[0].Foo));
+                Assert.IsTrue(comparer(odd, res[1].Foo));
+            }
+            else
+            {
+                Assert.AreEqual(even, res[0].Foo);
+                Assert.AreEqual(odd, res[1].Foo);
+            }
+        }
+
+        /// <summary>
+        /// Tests conditinal statement for structs with default and null values
+        /// </summary>
+        private void TestConditionalWithNullableStructs<T>(T? defaultFalue = null) where T : struct
+        {
+            var def = defaultFalue ?? default(T);
+            TestConditional(def, (T?) null);
+        }
+
+        public interface IPerson
+        {
+            int Age { get; set; }
+            string Name { get; set; }
+        }
+
+        public class Person : IBinarizable, IPerson
+        {
+            public Person(int age, string name)
+            {
+                Age = age;
+                Name = name;
+            }
+
+            [QuerySqlField(Name = "age1")] public int Age { get; set; }
+
+            [QuerySqlField] public string Name { get; set; }
+
+            [QuerySqlField] public Address Address { get; set; }
+
+            [QuerySqlField] public int OrganizationId { get; set; }
+
+            [QuerySqlField] public DateTime? Birthday { get; set; }
+
+            [QuerySqlField] public int AliasTest { get; set; }
+
+            public void WriteBinary(IBinaryWriter writer)
+            {
+                writer.WriteInt("age1", Age);
+                writer.WriteString("name", Name);
+                writer.WriteInt("OrganizationId", OrganizationId);
+                writer.WriteObject("Address", Address);
+                writer.WriteTimestamp("Birthday", Birthday);
+                writer.WriteInt("AliasTest", AliasTest);
+            }
+
+            public void ReadBinary(IBinaryReader reader)
+            {
+                Age = reader.ReadInt("age1");
+                Name = reader.ReadString("name");
+                OrganizationId = reader.ReadInt("OrganizationId");
+                Address = reader.ReadObject<Address>("Address");
+                Birthday = reader.ReadTimestamp("Birthday");
+                AliasTest = reader.ReadInt("AliasTest");
+            }
+        }
+
+        public class Address
+        {
+            [QuerySqlField] public int Zip { get; set; }
+            [QuerySqlField] public string Street { get; set; }
+            [QuerySqlField] public int AliasTest { get; set; }
+        }
+
+        public class Organization
+        {
+            [QuerySqlField] public int Id { get; set; }
+            [QuerySqlField] public string Name { get; set; }
+        }
+
+        public interface IRole
+        {
+            string Name { get; }
+            DateTime Date { get; }
+        }
+
+        public class Role : IRole
+        {
+            [QuerySqlField] public string Name { get; set; }
+            [QuerySqlField] public DateTime Date { get; set; }
+        }
+
+        public class Numerics
+        {
+            public Numerics(double val)
+            {
+                Double = val;
+                Float = (float) val;
+                Decimal = (decimal) val;
+                Int = (int) val;
+                Uint = (uint) val;
+                Long = (long) val;
+                Ulong = (ulong) val;
+                Short = (short) val;
+                Ushort = (ushort) val;
+                Byte = (byte) val;
+                Sbyte =  (sbyte) val;
+            }
+
+            [QuerySqlField] public double Double { get; set; }
+            [QuerySqlField] public float Float { get; set; }
+            [QuerySqlField] public decimal Decimal { get; set; }
+            [QuerySqlField] public int Int { get; set; }
+            [QuerySqlField] public uint Uint { get; set; }
+            [QuerySqlField] public long Long { get; set; }
+            [QuerySqlField] public ulong Ulong { get; set; }
+            [QuerySqlField] public short Short { get; set; }
+            [QuerySqlField] public ushort Ushort { get; set; }
+            [QuerySqlField] public byte Byte { get; set; }
+            [QuerySqlField] public sbyte Sbyte { get; set; }
+        }
+
+        public struct RoleKey : IEquatable<RoleKey>
+        {
+            private readonly int _foo;
+            private readonly long _bar;
+
+            public RoleKey(int foo, long bar)
+            {
+                _foo = foo;
+                _bar = bar;
+            }
+
+            [QuerySqlField(Name = "_foo")]
+            public int Foo
+            {
+                get { return _foo; }
+            }
+
+            [QuerySqlField(Name = "_bar")]
+            public long Bar
+            {
+                get { return _bar; }
+            }
+
+            public bool Equals(RoleKey other)
+            {
+                return _foo == other._foo && _bar == other._bar;
+            }
+
+            public override bool Equals(object obj)
+            {
+                if (ReferenceEquals(null, obj)) return false;
+                return obj is RoleKey && Equals((RoleKey) obj);
+            }
+
+            public override int GetHashCode()
+            {
+                unchecked
+                {
+                    return (_foo*397) ^ _bar.GetHashCode();
+                }
+            }
+
+            public static bool operator ==(RoleKey left, RoleKey right)
+            {
+                return left.Equals(right);
+            }
+
+            public static bool operator !=(RoleKey left, RoleKey right)
+            {
+                return !left.Equals(right);
+            }
+        }
+
+        /// <summary>
+        /// Epsilon comparer.
+        /// </summary>
+        private class NumericComparer : IComparer
+        {
+            /** <inheritdoc /> */
+            public int Compare(object x, object y)
+            {
+                if (Equals(x, y))
+                    return 0;
+
+                if (x is double)
+                {
+                    var dx = (double) x;
+                    var dy = (double) y;
+
+                    // Epsilon is proportional to the min value, but not too small.
+                    const double epsilon = 2E-10d;
+                    var min = Math.Min(Math.Abs(dx), Math.Abs(dy));
+                    var relEpsilon = Math.Max(min*epsilon, epsilon);
+
+                    // Compare with epsilon because some funcs return slightly different results.
+                    return Math.Abs((double) x - (double) y) < relEpsilon ? 0 : 1;
+                }
+
+                return ((IComparable) x).CompareTo(y);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.CompiledQuery.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.CompiledQuery.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.CompiledQuery.cs
new file mode 100644
index 0000000..1cd377e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.CompiledQuery.cs
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System.Linq;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests the compiled query with various constructs.
+        /// </summary>
+        [Test]
+        public void TestCompiledQuery()
+        {
+            var persons = GetPersonCache().AsCacheQueryable();
+            var roles = GetRoleCache().AsCacheQueryable();
+
+            // Embedded args
+            var qry0 = CompiledQuery.Compile(() => persons.Where(x => x.Key < 3 && x.Value.Name.Contains("son")));
+            Assert.AreEqual(3, qry0().Count());
+
+            // Lambda args
+            var qry1 = CompiledQuery.Compile((int minKey, int take, int skip) => persons.Where(x => x.Key > minKey)
+                .Take(take).Skip(skip));
+            Assert.AreEqual(3, qry1(-1, 3, 1).GetAll().Count);
+
+            qry1 = CompiledQuery.Compile((int skip, int take, int minKey) => persons.Where(x => x.Key > minKey)
+                .Take(take).Skip(skip));
+
+            Assert.AreEqual(5, qry1(2, 5, 20).GetAll().Count);
+
+            // Mixed args
+            var qry2 = CompiledQuery.Compile((int maxKey, int minKey) =>
+                persons.Where(x => x.Key < maxKey
+                                   && x.Value.Name.Contains("er")
+                                   && x.Value.Age < maxKey
+                                   && x.Key > minKey).Skip(2));
+
+            Assert.AreEqual(6, qry2(10, 1).Count());
+
+            // Join
+            var qry3 = CompiledQuery.Compile(() =>
+                roles.Join(persons, r => r.Key.Foo, p => p.Key, (r, p) => r.Value.Name));
+
+            Assert.AreEqual(RoleCount, qry3().Count());
+
+            // Join with subquery
+            var qry4 = CompiledQuery.Compile(
+                (int a, int b, string sep) =>
+                    roles
+                        .Where(x => x.Key.Bar > a)
+                        .OrderBy(x => x.Key.Bar)
+                        .Join(persons.Where(x => x.Key < b && x.Key > 0),
+                            r => r.Key.Foo,
+                            p => p.Value.Address.Zip,
+                            (r, p) => p.Value.Name + sep + r.Value.Name + "|")
+                        .Skip(a).Take(1000)
+            );
+
+            Assert.AreEqual(new[] { " Person_2  =Role_2|", " Person_3  =|" }, qry4(1, PersonCount, "=").ToArray());
+
+            // Union
+            var qry5 = CompiledQuery.Compile(() => roles.Select(x => -x.Key.Foo).Union(persons.Select(x => x.Key)));
+
+            Assert.AreEqual(RoleCount + PersonCount, qry5().Count());
+
+            // Projection
+            var qry6 = CompiledQuery.Compile((int minAge) => persons
+                .Select(x => x.Value)
+                .Where(x => x.Age >= minAge)
+                .Select(x => new { x.Name, x.Age })
+                .OrderBy(x => x.Name));
+
+            var res = qry6(PersonCount - 3).GetAll();
+
+            Assert.AreEqual(3, res.Count);
+            Assert.AreEqual(PersonCount - 3, res[0].Age);
+        }
+
+        /// <summary>
+        /// Tests the compiled query overloads.
+        /// </summary>
+        [Test]
+        public void TestCompiledQueryOverloads()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+
+            // const args are allowed
+            Assert.AreEqual(5, CompiledQuery.Compile(() => cache.Where(x => x.Key < 5))().GetAll().Count);
+
+            // 0 arg
+            var qry0 = CompiledQuery.Compile(() => cache.Select(x => x.Value.Name));
+            Assert.AreEqual(PersonCount, qry0().ToArray().Length);
+
+            // 1 arg
+            var qry1 = CompiledQuery.Compile((int k) => cache.Where(x => x.Key < k));
+            Assert.AreEqual(3, qry1(3).ToArray().Length);
+
+            // 1 arg twice
+            var qry1T = CompiledQuery.Compile((int k) => cache.Where(x => x.Key < k && x.Value.Age < k));
+            Assert.AreEqual(3, qry1T(3).ToArray().Length);
+
+            // 2 arg
+            var qry2 =
+                CompiledQuery.Compile((int i, string s) => cache.Where(x => x.Key < i && x.Value.Name.StartsWith(s)));
+            Assert.AreEqual(5, qry2(5, " Pe").ToArray().Length);
+
+            // Changed param order
+            var qry2R =
+                CompiledQuery.Compile((string s, int i) => cache.Where(x => x.Key < i && x.Value.Name.StartsWith(s)));
+            Assert.AreEqual(5, qry2R(" Pe", 5).ToArray().Length);
+
+            // 3 arg
+            var qry3 = CompiledQuery.Compile((int i, string s, double d) =>
+                cache.Where(x => x.Value.Address.Zip > d && x.Key < i && x.Value.Name.Contains(s)));
+            Assert.AreEqual(5, qry3(5, "son", -10).ToArray().Length);
+
+            // 4 arg
+            var qry4 = CompiledQuery.Compile((int a, int b, int c, int d) =>
+                cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d));
+            Assert.AreEqual(new[] { 3, 4 }, qry4(0, 1, 2, 5).ToArray());
+
+            // 5 arg
+            var qry5 = CompiledQuery.Compile((int a, int b, int c, int d, int e) =>
+                cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e));
+            Assert.AreEqual(new[] { 3, 4 }, qry5(0, 1, 2, 5, 6).ToArray());
+
+            // 6 arg
+            var qry6 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f) =>
+                cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e && k < f));
+            Assert.AreEqual(new[] { 3, 4 }, qry6(0, 1, 2, 5, 6, 7).ToArray());
+
+            // 7 arg
+            var qry7 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f, int g) =>
+                cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e && k < f && k < g));
+            Assert.AreEqual(new[] { 3, 4 }, qry7(0, 1, 2, 5, 6, 7, 8).ToArray());
+
+            // 8 arg
+            var qry8 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f, int g, int h) =>
+                cache.Select(x => x.Key)
+                    .Where(k => k > a && k > b && k > c && k < d && k < e && k < f && k < g && k < h));
+            Assert.AreEqual(new[] { 3, 4 }, qry8(0, 1, 2, 5, 6, 7, 8, 9).ToArray());
+        }
+
+        /// <summary>
+        /// Tests the free-form compiled query, where user provides an array of arguments.
+        /// </summary>
+        [Test]
+        public void TestCompiledQueryFreeform()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+
+            var qry = cache.Where(x => x.Key < 5);
+
+            // Simple
+            var compiled = CompiledQuery.Compile(qry);
+
+            Assert.AreEqual(5, compiled(5).Count());
+            Assert.AreEqual(6, compiled(6).Count());
+
+            // Select
+            var compiledSelect = CompiledQuery.Compile(qry.Select(x => x.Value.Name).OrderBy(x => x));
+
+            Assert.AreEqual(3, compiledSelect(3).Count());
+            Assert.AreEqual(" Person_0  ", compiledSelect(1).Single());
+
+            // Join
+            var compiledJoin = CompiledQuery.Compile(qry.Join(
+                GetOrgCache().AsCacheQueryable().Where(x => x.Value.Name.StartsWith("Org")),
+                p => p.Value.OrganizationId, o => o.Value.Id, (p, o) => o.Key));
+
+            Assert.AreEqual(1000, compiledJoin("Org", 1).Single());
+
+            // Many parameters
+            var qry2 = cache.Where(x => x.Key < 3)
+                .Where(x => x.Key > 0)
+                .Where(x => x.Value.Name.Contains(""))
+                .Where(x => x.Value.Address.Zip > 0)
+                .Where(x => x.Value.Age == 7);
+
+            var compiled2 = CompiledQuery.Compile(qry2);
+
+            Assert.AreEqual(17, compiled2(18, 16, "ers", 13, 17).Single().Key);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Contains.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Contains.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Contains.cs
new file mode 100644
index 0000000..032c746
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Contains.cs
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests IEnumerable.Contains.
+        /// </summary>
+        [Test]
+        public void TestContains()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+            var orgCache = GetOrgCache().AsCacheQueryable();
+
+            var keys = new[] { 1, 2, 3 };
+            var emptyKeys = new int[0];
+
+            var bigNumberOfKeys = 10000;
+            var aLotOfKeys = Enumerable.Range(-bigNumberOfKeys + 10 - PersonCount, bigNumberOfKeys + PersonCount)
+                .ToArray();
+            var hashSetKeys = new HashSet<int>(keys);
+            var defferedCollection = Enumerable.Range(1, 10)
+                .Select(i => new { Id = i })
+                .Select(arg => arg.Id);
+
+            CheckWhereFunc(cache, e => new[] { 1, 2, 3 }.Contains(e.Key));
+            CheckWhereFunc(cache, e => emptyKeys.Contains(e.Key));
+            CheckWhereFunc(cache, e => new int[0].Contains(e.Key));
+            CheckWhereFunc(cache, e => new int[0].Contains(e.Key));
+            CheckWhereFunc(cache, e => new List<int> { 1, 2, 3 }.Contains(e.Key));
+            CheckWhereFunc(cache, e => new List<int>(keys).Contains(e.Key));
+            CheckWhereFunc(cache, e => aLotOfKeys.Contains(e.Key));
+            CheckWhereFunc(cache, e => hashSetKeys.Contains(e.Key));
+            CheckWhereFunc(cache, e => !keys.Contains(e.Key));
+            CheckWhereFunc(cache, e => defferedCollection.Contains(e.Key));
+            CheckWhereFunc(orgCache, e => new[] { "Org_1", "NonExistentName", null }.Contains(e.Value.Name));
+            CheckWhereFunc(orgCache, e => !new[] { "Org_1", "NonExistentName", null }.Contains(e.Value.Name));
+            CheckWhereFunc(orgCache, e => new[] { "Org_1", null, null }.Contains(e.Value.Name));
+            CheckWhereFunc(orgCache, e => !new[] { "Org_1", null, null }.Contains(e.Value.Name));
+            CheckWhereFunc(orgCache, e => new string[] { null }.Contains(e.Value.Name));
+            CheckWhereFunc(orgCache, e => !new string[] { null }.Contains(e.Value.Name));
+            CheckWhereFunc(orgCache, e => !new string[] { null, null }.Contains(e.Value.Name));
+            CheckWhereFunc(orgCache, e => new string[] { null, null }.Contains(e.Value.Name));
+
+            //check passing a null object as collection
+            int[] nullKeys = null;
+            var nullKeysEntries = cache
+                .Where(e => nullKeys.Contains(e.Key))
+                .ToArray();
+            Assert.AreEqual(0, nullKeysEntries.Length, "Evaluating 'null.Contains' should return zero results");
+
+
+            Func<int[]> getKeysFunc = () => null;
+            var funcNullKeyEntries = cache
+                .Where(e => getKeysFunc().Contains(e.Key))
+                .ToArray();
+            Assert.AreEqual(0, funcNullKeyEntries.Length, "Evaluating 'null.Contains' should return zero results");
+
+
+            // Check subselect from other cache
+            var subSelectCount = cache
+                .Count(entry => orgCache
+                    .Where(orgEntry => orgEntry.Value.Name == "Org_1")
+                    .Select(orgEntry => orgEntry.Key)
+                    .Contains(entry.Value.OrganizationId));
+            var orgNumberOne = orgCache
+                .Where(orgEntry => orgEntry.Value.Name == "Org_1")
+                .Select(orgEntry => orgEntry.Key)
+                .First();
+            var subSelectCheckCount = cache.Count(entry => entry.Value.OrganizationId == orgNumberOne);
+            Assert.AreEqual(subSelectCheckCount, subSelectCount, "subselecting another CacheQueryable failed");
+
+            var ex = Assert.Throws<NotSupportedException>(() =>
+                CompiledQuery.Compile((int[] k) => cache.Where(x => k.Contains(x.Key))));
+            Assert.AreEqual("'Contains' clause on compiled query parameter is not supported.", ex.Message);
+
+            // check subquery from another cache put in separate variable
+            var orgIds = orgCache
+                .Where(o => o.Value.Name == "Org_1")
+                .Select(o => o.Key);
+
+            var subQueryFromVar = cache
+                .Where(x => orgIds.Contains(x.Value.OrganizationId))
+                .ToArray();
+
+            var subQueryInline = cache
+                .Where(x => orgCache.Where(o => o.Value.Name == "Org_1")
+                    .Select(o => o.Key).Contains(x.Value.OrganizationId))
+                .ToArray();
+
+            Assert.AreEqual(subQueryInline.Length, subQueryFromVar.Length);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Custom.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Custom.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Custom.cs
new file mode 100644
index 0000000..f797b4c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Custom.cs
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests the RemoveAll extension.
+        /// </summary>
+        [Test]
+        public void TestRemoveAll()
+        {
+            // Use new cache to avoid touching static data.
+            var cache = Ignition.GetIgnite().CreateCache<int, Person>(new CacheConfiguration("deleteAllTest",
+                new QueryEntity(typeof(int), typeof(Person)))
+            {
+                SqlEscapeAll = GetSqlEscapeAll()
+            });
+
+            Enumerable.Range(1, 10).ToList().ForEach(x => cache.Put(x, new Person(x, x.ToString())));
+
+            var queryable = cache.AsCacheQueryable();
+
+            Func<int[]> getKeys = () => cache.Select(x => x.Key).OrderBy(x => x).ToArray();
+
+            // Without predicate.
+            var res = queryable.Where(x => x.Key < 3).RemoveAll();
+            Assert.AreEqual(2, res);
+            Assert.AreEqual(Enumerable.Range(3, 8), getKeys());
+
+            // With predicate.
+            res = queryable.RemoveAll(x => x.Key < 7);
+            Assert.AreEqual(4, res);
+            Assert.AreEqual(Enumerable.Range(7, 4), getKeys());
+
+            // Subquery-style join.
+            var ids = GetPersonCache().AsCacheQueryable().Where(x => x.Key == 7).Select(x => x.Key);
+
+            res = queryable.Where(x => ids.Contains(x.Key)).RemoveAll();
+            Assert.AreEqual(1, res);
+            Assert.AreEqual(Enumerable.Range(8, 3), getKeys());
+
+            // Row number limit.
+            res = queryable.Take(2).RemoveAll();
+            Assert.AreEqual(2, res);
+            Assert.AreEqual(1, getKeys().Length);
+
+            // Unconditional.
+            queryable.RemoveAll();
+            Assert.AreEqual(0, cache.GetSize());
+
+            // Skip is not supported with DELETE.
+            var nex = Assert.Throws<NotSupportedException>(() => queryable.Skip(1).RemoveAll());
+            Assert.AreEqual(
+                "RemoveAll can not be combined with result operators (other than Take): SkipResultOperator",
+                nex.Message);
+
+            // Multiple result operators are not supported with DELETE.
+            nex = Assert.Throws<NotSupportedException>(() => queryable.Skip(1).Take(1).RemoveAll());
+            Assert.AreEqual(
+                "RemoveAll can not be combined with result operators (other than Take): SkipResultOperator, " +
+                "TakeResultOperator, RemoveAllResultOperator", nex.Message);
+
+            // Joins are not supported in H2.
+            var qry = queryable
+                .Where(x => x.Key == 7)
+                .Join(GetPersonCache().AsCacheQueryable(), p => p.Key, p => p.Key, (p1, p2) => p1);
+
+            var ex = Assert.Throws<IgniteException>(() => qry.RemoveAll());
+            Assert.AreEqual("Failed to parse query", ex.Message.Substring(0, 21));
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.DateTime.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.DateTime.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.DateTime.cs
new file mode 100644
index 0000000..b869dc4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.DateTime.cs
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Linq;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests date time.
+        /// </summary>
+        [Test]
+        public void TestDateTime()
+        {
+            var roles = GetRoleCache().AsCacheQueryable();
+            var persons = GetPersonCache().AsCacheQueryable();
+
+            // Invalid dateTime
+            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+            var ex = Assert.Throws<BinaryObjectException>(() =>
+                roles.Where(x => x.Value.Date > DateTime.Now).ToArray());
+            Assert.AreEqual("DateTime is not UTC. Only UTC DateTime can be used for interop with other platforms.",
+                ex.Message);
+
+            // Test retrieval
+            var dates = roles.OrderBy(x => x.Value.Date).Select(x => x.Value.Date);
+            var expDates = GetRoleCache().Select(x => x.Value.Date).OrderBy(x => x).ToArray();
+            Assert.AreEqual(expDates, dates.ToArray());
+
+            // Filtering
+            Assert.AreEqual(1, persons.Count(x => x.Value.Birthday == StartDateTime));
+            Assert.AreEqual(PersonCount, persons.Count(x => x.Value.Birthday >= StartDateTime));
+            Assert.Greater(persons.Count(x => x.Value.Birthday > DateTime.UtcNow), 1);
+
+            // Joins
+            var join =
+                from role in roles
+                join person in persons on role.Value.Date equals person.Value.Birthday
+                select person;
+
+            Assert.AreEqual(2, join.Count());
+
+            // Functions
+            var strings = dates.Select(x => x.ToString("dd MM YYYY HH:mm:ss")).ToArray();
+            Assert.AreEqual(new[] { "17 05 2000 15:04:05", "29 12 2000 23:04:05", "17 05 2001 15:04:05" }, strings);
+
+            // Properties
+            Assert.AreEqual(new[] { 2000, 2000, 2001 }, dates.Select(x => x.Year).ToArray());
+            Assert.AreEqual(new[] { 5, 12, 5 }, dates.Select(x => x.Month).ToArray());
+            Assert.AreEqual(new[] { 17, 29, 17 }, dates.Select(x => x.Day).ToArray());
+            Assert.AreEqual(expDates.Select(x => x.DayOfYear).ToArray(), dates.Select(x => x.DayOfYear).ToArray());
+            Assert.AreEqual(expDates.Select(x => x.DayOfWeek).ToArray(), dates.Select(x => x.DayOfWeek).ToArray());
+            Assert.AreEqual(new[] { 15, 23, 15 }, dates.Select(x => x.Hour).ToArray());
+            Assert.AreEqual(new[] { 4, 4, 4 }, dates.Select(x => x.Minute).ToArray());
+            Assert.AreEqual(new[] { 5, 5, 5 }, dates.Select(x => x.Second).ToArray());
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Functions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Functions.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Functions.cs
new file mode 100644
index 0000000..a672d5a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Functions.cs
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System.Linq;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests where clause.
+        /// </summary>
+        [Test]
+        public void TestWhere()
+        {
+            var cache = GetPersonCache().AsCacheQueryable();
+
+            // Test const and var parameters
+            const int age = 10;
+            var key = 15;
+
+            Assert.AreEqual(age, cache.Where(x => x.Value.Age < age).ToArray().Length);
+            Assert.AreEqual(age, cache.Where(x => x.Value.Address.Zip < age).ToArray().Length);
+            Assert.AreEqual(19, cache.Where(x => x.Value.Age > age && x.Value.Age < 30).ToArray().Length);
+            Assert.AreEqual(20, cache.Where(x => x.Value.Age > age).Count(x => x.Value.Age < 30 || x.Value.Age == 50));
+            Assert.AreEqual(key, cache.Where(x => x.Key < key).ToArray().Length);
+            Assert.AreEqual(key, cache.Where(x => -x.Key > -key).ToArray().Length);
+
+            Assert.AreEqual(1, GetRoleCache().AsCacheQueryable().Where(x => x.Key.Foo < 2).ToArray().Length);
+            Assert.AreEqual(2, GetRoleCache().AsCacheQueryable().Where(x => x.Key.Bar > 2 && x.Value.Name != "11")
+                .ToArray().Length);
+        }
+
+        /// <summary>
+        /// Tests the group by.
+        /// </summary>
+        [Test]
+        public void TestGroupBy()
+        {
+            var persons = GetPersonCache().AsCacheQueryable();
+            var orgs = GetOrgCache().AsCacheQueryable();
+
+            // Simple, unordered
+            CollectionAssert.AreEquivalent(new[] { 1000, 1001 },
+                persons.GroupBy(x => x.Value.OrganizationId).Select(x => x.Key).ToArray());
+
+            // Aggregate
+            Assert.AreEqual(1000,
+                persons.GroupBy(x => x.Value.OrganizationId).Select(x => x.Key).OrderBy(x => x).First());
+
+            // Ordering and count
+            var res1 =
+                from p in persons
+                orderby p.Value.Name
+                group p by p.Value.OrganizationId
+                into gs
+                orderby gs.Key
+                where gs.Count() > 10
+                select new { Count = gs.Count(), OrgId = gs.Key, AvgAge = gs.Average(x => x.Value.Age) };
+
+            var resArr = res1.ToArray();
+
+            Assert.AreEqual(new[]
+            {
+                new {Count = PersonCount/2, OrgId = 1000, AvgAge = (double) PersonCount/2 - 1},
+                new {Count = PersonCount/2, OrgId = 1001, AvgAge = (double) PersonCount/2}
+            }, resArr);
+
+            // Join and sum
+            var res2 = persons.Join(orgs.Where(o => o.Key > 10), p => p.Value.OrganizationId, o => o.Key,
+                    (p, o) => new { p, o })
+                .GroupBy(x => x.o.Value.Name)
+                .Select(g => new { Org = g.Key, AgeSum = g.Select(x => x.p.Value.Age).Sum() });
+
+            var resArr2 = res2.ToArray();
+
+            Assert.AreEqual(new[]
+            {
+                new {Org = "Org_0", AgeSum = persons.Where(x => x.Value.OrganizationId == 1000).Sum(x => x.Value.Age)},
+                new {Org = "Org_1", AgeSum = persons.Where(x => x.Value.OrganizationId == 1001).Sum(x => x.Value.Age)}
+            }, resArr2);
+        }
+
+        /// <summary>
+        /// Tests the union.
+        /// </summary>
+        [Test]
+        public void TestUnion()
+        {
+            // Direct union
+            var persons = GetPersonCache().AsCacheQueryable();
+            var persons2 = GetSecondPersonCache().AsCacheQueryable();
+
+            var res = persons.Union(persons2).ToArray();
+
+            Assert.AreEqual(PersonCount * 2, res.Length);
+
+            // Subquery
+            var roles = GetRoleCache().AsCacheQueryable().Select(x => -x.Key.Foo);
+            var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Union(roles).ToArray();
+
+            Assert.AreEqual(RoleCount + PersonCount, ids.Length);
+        }
+
+        /// <summary>
+        /// Tests intersect.
+        /// </summary>
+        [Test]
+        public void TestIntersect()
+        {
+            // Direct intersect
+            var persons = GetPersonCache().AsCacheQueryable();
+            var persons2 = GetSecondPersonCache().AsCacheQueryable();
+
+            var res = persons.Intersect(persons2).ToArray();
+
+            Assert.AreEqual(0, res.Length);
+
+            // Subquery
+            var roles = GetRoleCache().AsCacheQueryable().Select(x => x.Key.Foo);
+            var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Intersect(roles).ToArray();
+
+            Assert.AreEqual(RoleCount, ids.Length);
+        }
+
+        /// <summary>
+        /// Tests except.
+        /// </summary>
+        [Test]
+        public void TestExcept()
+        {
+            // Direct except
+            var persons = GetPersonCache().AsCacheQueryable();
+            var persons2 = GetSecondPersonCache().AsCacheQueryable();
+
+            var res = persons.Except(persons2).ToArray();
+
+            Assert.AreEqual(PersonCount, res.Length);
+
+            // Subquery
+            var roles = GetRoleCache().AsCacheQueryable().Select(x => x.Key.Foo);
+            var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Except(roles).ToArray();
+
+            Assert.AreEqual(PersonCount - RoleCount, ids.Length);
+        }
+
+        /// <summary>
+        /// Tests ordering.
+        /// </summary>
+        [Test]
+        public void TestOrdering()
+        {
+            var persons = GetPersonCache().AsCacheQueryable()
+                .OrderByDescending(x => x.Key)
+                .ThenBy(x => x.Value.Age)
+                .ToArray();
+
+            Assert.AreEqual(Enumerable.Range(0, PersonCount).Reverse().ToArray(),
+                persons.Select(x => x.Key).ToArray());
+
+            var personsByOrg = GetPersonCache().AsCacheQueryable()
+                .Join(GetOrgCache().AsCacheQueryable(), p => p.Value.OrganizationId, o => o.Value.Id,
+                    (p, o) => new
+                    {
+                        PersonId = p.Key,
+                        PersonName = p.Value.Name.ToUpper(),
+                        OrgName = o.Value.Name
+                    })
+                .OrderBy(x => x.OrgName.ToLower())
+                .ThenBy(x => x.PersonName)
+                .ToArray();
+
+            var expectedIds = Enumerable.Range(0, PersonCount)
+                .OrderBy(x => (x % 2).ToString())
+                .ThenBy(x => x.ToString())
+                .ToArray();
+
+            var actualIds = personsByOrg.Select(x => x.PersonId).ToArray();
+
+            Assert.AreEqual(expectedIds, actualIds);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
new file mode 100644
index 0000000..9430dd8
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache.Query;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests the introspection.
+        /// </summary>
+        [Test]
+        public void TestIntrospection()
+        {
+            var cache = GetPersonCache();
+
+            // Check regular query
+            var query = cache.AsCacheQueryable(new QueryOptions
+            {
+                Local = true,
+                PageSize = 999,
+                EnforceJoinOrder = true,
+                Timeout = TimeSpan.FromSeconds(2.5),
+                ReplicatedOnly = true,
+                Colocated = true
+            }).Where(x => x.Key > 10).ToCacheQueryable();
+
+            Assert.AreEqual(cache.Name, query.CacheName);
+            Assert.AreEqual(cache.Ignite, query.Ignite);
+
+            var fq = query.GetFieldsQuery();
+
+            Assert.AreEqual(
+                GetSqlEscapeAll()
+                    ? "select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where (_T0.\"_KEY\" > ?)"
+                    : "select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where (_T0._KEY > ?)",
+                fq.Sql);
+
+            Assert.AreEqual(new[] { 10 }, fq.Arguments);
+            Assert.IsTrue(fq.Local);
+            Assert.AreEqual(PersonCount - 11, cache.QueryFields(fq).GetAll().Count);
+            Assert.AreEqual(999, fq.PageSize);
+            Assert.IsFalse(fq.EnableDistributedJoins);
+            Assert.IsTrue(fq.EnforceJoinOrder);
+            Assert.IsTrue(fq.ReplicatedOnly);
+            Assert.IsTrue(fq.Colocated);
+            Assert.AreEqual(TimeSpan.FromSeconds(2.5), fq.Timeout);
+
+            var str = query.ToString();
+            Assert.AreEqual(GetSqlEscapeAll()
+                ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
+                  "(_T0.\"_KEY\" > ?), Arguments=[10], " +
+                  "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
+                  "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]"
+                : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
+                  "(_T0._KEY > ?), Arguments=[10], " +
+                  "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
+                  "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]", str);
+
+            // Check fields query
+            var fieldsQuery = (ICacheQueryable)cache.AsCacheQueryable().Select(x => x.Value.Name);
+
+            Assert.AreEqual(cache.Name, fieldsQuery.CacheName);
+            Assert.AreEqual(cache.Ignite, fieldsQuery.Ignite);
+
+            fq = fieldsQuery.GetFieldsQuery();
+            Assert.AreEqual(GetSqlEscapeAll()
+                    ? "select _T0.\"Name\" from \"person_org\".\"Person\" as _T0"
+                    : "select _T0.NAME from \"person_org\".Person as _T0",
+                fq.Sql);
+
+            Assert.IsFalse(fq.Local);
+            Assert.AreEqual(SqlFieldsQuery.DefaultPageSize, fq.PageSize);
+            Assert.IsFalse(fq.EnableDistributedJoins);
+            Assert.IsFalse(fq.EnforceJoinOrder);
+
+            str = fieldsQuery.ToString();
+            Assert.AreEqual(GetSqlEscapeAll()
+                ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+                  "[Sql=select _T0.\"Name\" from \"person_org\".\"Person\" as _T0, Arguments=[], Local=False, " +
+                  "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
+                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
+                : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+                  "[Sql=select _T0.NAME from \"person_org\".Person as _T0, Arguments=[], Local=False, " +
+                  "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
+                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
+
+            // Check distributed joins flag propagation
+            var distrQuery = cache.AsCacheQueryable(new QueryOptions { EnableDistributedJoins = true })
+                .Where(x => x.Key > 10 && x.Value.Age > 20 && x.Value.Name.Contains("x"));
+
+            query = distrQuery.ToCacheQueryable();
+
+            Assert.IsTrue(query.GetFieldsQuery().EnableDistributedJoins);
+
+            str = distrQuery.ToString();
+            Assert.AreEqual(GetSqlEscapeAll()
+                ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
+                  "(((_T0.\"_KEY\" > ?) and (_T0.\"age1\" > ?)) " +
+                  "and (_T0.\"Name\" like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
+                  "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
+                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
+                : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
+                  "(((_T0._KEY > ?) and (_T0.AGE1 > ?)) " +
+                  "and (_T0.NAME like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
+                  "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
+                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.LocalCollection.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.LocalCollection.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.LocalCollection.cs
new file mode 100644
index 0000000..e7e05f4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.LocalCollection.cs
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System.Collections.Generic;
+    using System.Linq;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests the join with local collection.
+        /// </summary>
+        [Test]
+        public void TestLocalJoin()
+        {
+            var persons = GetPersonCache().AsCacheQueryable();
+            var orgs = GetOrgCache().AsCacheQueryable();
+
+            var localOrgs = orgs
+                .Select(e => e.Value)
+                .ToArray();
+
+            var allOrganizationIds = localOrgs
+                .Select(e => e.Id)
+                .ToArray();
+
+            // Join with local collection 
+            var qry1 = persons.Join(allOrganizationIds,
+                    pe => pe.Value.OrganizationId,
+                    i => i,
+                    (pe, o) => pe
+                )
+                .ToArray();
+
+            Assert.AreEqual(PersonCount, qry1.Length);
+
+            // Join using expression in innerKeySelector
+            var qry2 = persons.Join(allOrganizationIds,
+                    pe => pe.Value.OrganizationId,
+                    i => i + 1 - 1,
+                    (pe, o) => pe
+                )
+                .ToArray();
+
+            Assert.AreEqual(PersonCount, qry2.Length);
+
+            // Local collection subquery
+            var qry3 = persons.Join(localOrgs.Select(e => e.Id),
+                    pe => pe.Value.OrganizationId,
+                    i => i,
+                    (pe, o) => pe
+                )
+                .ToArray();
+
+            Assert.AreEqual(PersonCount, qry3.Length);
+
+            // Compiled query
+            var qry4 = CompiledQuery.Compile(() => persons.Join(allOrganizationIds,
+                pe => pe.Value.OrganizationId,
+                i => i,
+                (pe, o) => pe
+            ));
+
+            Assert.AreEqual(PersonCount, qry4().Count());
+
+            // Compiled query with outer join
+            var qry4A = CompiledQuery.Compile(() => persons.Join(new int[] { }.DefaultIfEmpty(),
+                pe => pe.Value.OrganizationId,
+                i => i,
+                (pe, o) => pe
+            ));
+
+            Assert.AreEqual(PersonCount, qry4A().Count());
+
+            // Compiled query
+            var qry5 = CompiledQuery.Compile(() => persons.Join(new[] { -1, -2 }.DefaultIfEmpty(),
+                pe => pe.Value.OrganizationId,
+                i => i,
+                (pe, o) => pe
+            ));
+
+            Assert.AreEqual(PersonCount, qry5().Count());
+
+            // Outer join
+            var qry6 = persons.Join(new[] { -1, -2 }.DefaultIfEmpty(),
+                    pe => pe.Value.OrganizationId,
+                    i => i,
+                    (pe, o) => pe
+                )
+                .ToArray();
+
+            Assert.AreEqual(PersonCount, qry6.Length);
+
+            // Join with local list
+            var qry7 = persons.Join(new List<int> { 1000, 1001, 1002, 1003 },
+                    pe => pe.Value.OrganizationId,
+                    i => i,
+                    (pe, o) => pe
+                )
+                .ToArray();
+
+            Assert.AreEqual(PersonCount, qry7.Length);
+
+            // Join with local list variable
+            var list = new List<int> { 1000, 1001, 1002, 1003 };
+            var qry8 = persons.Join(list,
+                    pe => pe.Value.OrganizationId,
+                    i => i,
+                    (pe, o) => pe
+                )
+                .ToArray();
+
+            Assert.AreEqual(PersonCount, qry8.Length);
+        }
+
+        /// <summary>
+        /// Tests the compiled query containing join with local collection passed as parameter.
+        /// </summary>
+        [Test]
+        [Ignore("IGNITE-5404")]
+        public void TestLocalJoinCompiledQueryParameter()
+        {
+            var persons = GetPersonCache().AsCacheQueryable();
+            var orgs = GetOrgCache().AsCacheQueryable();
+
+            var localOrgs = orgs
+                .Select(e => e.Value)
+                .ToArray();
+
+            var allOrganizationIds = localOrgs
+                .Select(e => e.Id)
+                .ToArray();
+
+            // Join with local collection passed as parameter
+            var qry1 = CompiledQuery.Compile((IEnumerable<int> lc) => persons.Join(lc,
+                pe => pe.Value.OrganizationId,
+                i => i,
+                (pe, o) => pe
+            ));
+
+            Assert.AreEqual(PersonCount, qry1(allOrganizationIds).Count());
+
+            //Compiled query with outer join
+            var qry2 = CompiledQuery.Compile((IEnumerable<int> lc) => persons.Join(lc.DefaultIfEmpty(),
+                pe => pe.Value.OrganizationId,
+                i => i,
+                (pe, o) => pe
+            ));
+
+            Assert.AreEqual(PersonCount, qry2(new[] { -11 }).Count());
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
new file mode 100644
index 0000000..f589329
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+    using System;
+    using System.Linq;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests LINQ.
+    /// </summary>
+    public partial class CacheLinqTest
+    {
+        /// <summary>
+        /// Tests the same cache join.
+        /// </summary>
+        [Test]
+        public void TestSameCacheJoin()
+        {
+            // Select persons in specific organization
+            var organizations = GetOrgCache().AsCacheQueryable();
+            var persons = GetPersonCache().AsCacheQueryable();
+
+            var res = persons.Join(organizations, person => person.Value.OrganizationId + 3, org => org.Value.Id + 3,
+                    (person, org) => new { Person = person.Value, Org = org.Value })
+                .Where(x => x.Org.Name == "Org_1")
+                .ToList();
+
+            Assert.AreEqual(PersonCount / 2, res.Count);
+
+            Assert.IsTrue(res.All(r => r.Person.OrganizationId == r.Org.Id));
+
+            // Test full projection (selects pair of ICacheEntry)
+            var res2 = persons.Join(organizations, person => person.Value.OrganizationId - 1, org => org.Value.Id - 1,
+                    (person, org) => new { Person = person, Org = org })
+                .Where(x => x.Org.Value.Name.ToLower() == "org_0")
+                .ToList();
+
+            Assert.AreEqual(PersonCount / 2, res2.Count);
+        }
+
+        /// <summary>
+        /// Tests the multi key join.
+        /// </summary>
+        [Test]
+        public void TestMultiKeyJoin()
+        {
+            var organizations = GetOrgCache().AsCacheQueryable();
+            var persons = GetPersonCache().AsCacheQueryable();
+
+            var multiKey =
+                from person in persons
+                join org in organizations on
+                new { OrgId = person.Value.OrganizationId, person.Key } equals
+                new { OrgId = org.Value.Id, Key = org.Key - 1000 }
+                where person.Key == 1
+                select new { PersonName = person.Value.Name, OrgName = org.Value.Name };
+
+            Assert.AreEqual(" Person_1  ", multiKey.Single().PersonName);
+        }
+
+        /// <summary>
+        /// Tests the cross cache join.
+        /// </summary>
+        [Test]
+        public void TestCrossCacheJoin()
+        {
+            var persons = GetPersonCache().AsCacheQueryable();
+            var roles = GetRoleCache().AsCacheQueryable();
+
+            var res = persons.Join(roles, person => person.Key, role => role.Key.Foo, (person, role) => role)
+                .OrderBy(x => x.Key.Bar)
+                .ToArray();
+
+            Assert.AreEqual(RoleCount, res.Length);
+            Assert.AreEqual(101, res[0].Key.Bar);
+        }
+
+        /// <summary>
+        /// Tests the cross cache join.
+        /// </summary>
+        [Test]
+        public void TestCrossCacheJoinInline()
+        {
+            var res = GetPersonCache().AsCacheQueryable().Join(GetRoleCache().AsCacheQueryable(),
+                    person => person.Key, role => role.Key.Foo, (person, role) => role)
+                .OrderBy(x => x.Key.Bar).ToArray();
+
+            Assert.AreEqual(RoleCount, res.Length);
+            Assert.AreEqual(101, res[0].Key.Bar);
+        }
+
+        /// <summary>
+        /// Tests the multi cache join.
+        /// </summary>
+        [Test]
+        public void TestMultiCacheJoin()
+        {
+            var organizations = GetOrgCache().AsCacheQueryable();
+            var persons = GetPersonCache().AsCacheQueryable();
+            var roles = GetRoleCache().AsCacheQueryable();
+
+            var res = roles.Join(persons, role => role.Key.Foo, person => person.Key,
+                    (role, person) => new { person, role })
+                .Join(organizations, pr => pr.person.Value.OrganizationId, org => org.Value.Id,
+                    (pr, org) => new { org, pr.person, pr.role }).ToArray();
+
+            Assert.AreEqual(RoleCount, res.Length);
+        }
+
+        /// <summary>
+        /// Tests the multi cache join subquery.
+        /// </summary>
+        [Test]
+        public void TestMultiCacheJoinSubquery()
+        {
+            var organizations = GetOrgCache().AsCacheQueryable().Where(x => x.Key == 1001);
+            var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < 20);
+            var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Key.Foo >= 0);
+
+            var res = roles.Join(persons, role => role.Key.Foo, person => person.Key,
+                    (role, person) => new { person, role })
+                .Join(organizations, pr => pr.person.Value.OrganizationId, org => org.Value.Id,
+                    (pr, org) => new { org, pr.person, pr.role }).ToArray();
+
+            Assert.AreEqual(2, res.Length);
+        }
+
+        /// <summary>
+        /// Tests the outer join.
+        /// </summary>
+        [Test]
+        public void TestOuterJoin()
+        {
+            var persons = GetPersonCache().AsCacheQueryable();
+            var roles = GetRoleCache().AsCacheQueryable();
+
+            var res = persons.Join(roles.Where(r => r.Key.Bar > 0).DefaultIfEmpty(),
+                    person => person.Key, role => role.Key.Foo,
+                    (person, role) => new
+                    {
+                        PersonName = person.Value.Name,
+                        RoleName = role.Value.Name
+                    })
+                .Where(x => x.PersonName != " ")
+                .ToArray();
+
+            Assert.AreEqual(PersonCount, res.Length);
+        }
+
+        /// <summary>
+        /// Tests the subquery join.
+        /// </summary>
+        [Test]
+        public void TestSubqueryJoin()
+        {
+            var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key >= 0);
+
+            var orgs = GetOrgCache().AsCacheQueryable().Where(x => x.Key > 10);
+
+            var qry1 = persons.Join(orgs,
+                    p => p.Value.OrganizationId,
+                    o => o.Value.Id,
+                    (p, o) => p)
+                .Where(x => x.Key >= 0)
+                .ToList();
+
+            Assert.AreEqual(PersonCount, qry1.Count);
+
+            // With selector inline
+            var qry2 = persons
+                .Join(orgs.Select(orgEntry => orgEntry.Key),
+                    e => e.Value.OrganizationId,
+                    i => i,
+                    (e, i) => e)
+                .ToList();
+
+            Assert.AreEqual(PersonCount, qry2.Count);
+
+            // With selector from variable
+            var innerSequence = orgs
+                .Select(orgEntry => orgEntry.Key);
+
+            var qry3 = persons
+                .Join(innerSequence,
+                    e => e.Value.OrganizationId,
+                    i => i,
+                    (e, i) => e)
+                .ToList();
+
+            Assert.AreEqual(PersonCount, qry3.Count);
+        }
+
+        /// <summary>
+        /// Tests the invalid join.
+        /// </summary>
+        [Test]
+        public void TestInvalidJoin()
+        {
+            var localComplexTypeCollection = GetOrgCache().AsCacheQueryable()
+                .Select(e => e.Value)
+                .ToArray();
+
+            // Join on non-IQueryable with complex(not supported) type
+            var ex = Assert.Throws<NotSupportedException>(() =>
+                // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+            {
+                GetPersonCache().AsCacheQueryable().Join(localComplexTypeCollection, p => p.Value.OrganizationId,
+                    o => o.Id, (p, o) => p).ToList();
+            });
+
+            Assert.IsTrue(ex.Message.StartsWith("Not supported item type for Join with local collection"));
+        }
+
+        /// <summary>
+        /// Tests query with multiple from clause.
+        /// </summary>
+        [Test]
+        public void TestMultipleFrom()
+        {
+            var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < PersonCount);
+            var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Value.Name != "1");
+
+            var all = persons.SelectMany(person => roles.Select(role => new { role, person }));
+            Assert.AreEqual(RoleCount * PersonCount, all.Count());
+
+            var filtered =
+                from person in persons
+                from role in roles
+                where person.Key == role.Key.Foo
+                select new { Person = person.Value.Name, Role = role.Value.Name };
+
+            var res = filtered.ToArray();
+
+            Assert.AreEqual(RoleCount, res.Length);
+        }
+
+        /// <summary>
+        /// Tests query with multiple from clause with inline query sources.
+        /// </summary>
+        [Test]
+        public void TestMultipleFromInline()
+        {
+            var filtered =
+                from person in GetPersonCache().AsCacheQueryable()
+                from role in GetRoleCache().AsCacheQueryable()
+                where person.Key == role.Key.Foo
+                select new { Person = person.Value.Name, Role = role.Value.Name };
+
+            var res = filtered.ToArray();
+
+            Assert.AreEqual(RoleCount, res.Length);
+        }
+
+        /// <summary>
+        /// Tests the join of a table to itself.
+        /// </summary>
+        [Test]
+        public void TestSelfJoin()
+        {
+            // Different queryables
+            var p1 = GetPersonCache().AsCacheQueryable();
+            var p2 = GetPersonCache().AsCacheQueryable();
+
+            var qry = p1.Join(p2, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
+            Assert.AreEqual(PersonCount, qry.ToArray().Distinct().Count());
+
+            // Same queryables
+            var qry2 = p1.Join(p1, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
+            Assert.AreEqual(PersonCount, qry2.ToArray().Distinct().Count());
+        }
+
+        /// <summary>
+        /// Tests the join of a table to itself with inline queryable.
+        /// </summary>
+        [Test]
+        public void TestSelfJoinInline()
+        {
+            var qry = GetPersonCache().AsCacheQueryable().Join(GetPersonCache().AsCacheQueryable(),
+                x => x.Value.Age, x => x.Key, (x, y) => x.Key);
+
+            Assert.AreEqual(PersonCount, qry.ToArray().Distinct().Count());
+        }
+    }
+}
\ No newline at end of file