ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [16/33] ignite git commit: IGNITE-6244 .NET: Thin client: ScanQuery
Date Wed, 20 Sep 2017 12:48:14 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ScanQueryTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ScanQueryTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ScanQueryTest.cs
new file mode 100644
index 0000000..bc1e8ee
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ScanQueryTest.cs
@@ -0,0 +1,241 @@
+/*
+ * 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.Client.Cache
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Cache.Query;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Configuration;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests scan queries.
+    /// </summary>
+    public class ScanQueryTest : ClientTestBase
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScanQueryTest"/> class.
+        /// </summary>
+        public ScanQueryTest() : base(2)
+        {
+            // No-op.
+        }
+
+        /** <inheritdoc /> */
+        protected override IgniteConfiguration GetIgniteConfiguration()
+        {
+            var cfg = base.GetIgniteConfiguration();
+
+            cfg.SqlConnectorConfiguration = new SqlConnectorConfiguration
+            {
+                MaxOpenCursorsPerConnection = 3
+            };
+
+            return cfg;
+        }
+
+        /// <summary>
+        /// Tests scan query without filter.
+        /// </summary>
+        [Test]
+        [SuppressMessage("ReSharper", "ReturnValueOfPureMethodIsNotUsed")]
+        public void TestNoFilter()
+        {
+            var cache = GetPersonCache();
+
+            Action<IEnumerable<ICacheEntry<int, Person>>> checkResults = e =>
+            {
+                Assert.AreEqual(cache.Select(x => x.Value.Name).OrderBy(x => x).ToArray(),
+                    e.Select(x => x.Value.Name).OrderBy(x => x).ToArray());
+            };
+
+            using (var client = GetClient())
+            {
+                var clientCache = client.GetCache<int, Person>(CacheName);
+
+                var query = new ScanQuery<int, Person>();
+
+                // GetAll.
+                var cursor = clientCache.Query(query);
+                checkResults(cursor.GetAll());
+
+                // Can't iterate or call GetAll again.
+                Assert.Throws<InvalidOperationException>(() => cursor.ToArray());
+                Assert.Throws<InvalidOperationException>(() => cursor.GetAll());
+
+                // Iterator.
+                using (cursor = clientCache.Query(query))
+                {
+                    checkResults(cursor.ToArray());
+
+                    // Can't iterate or call GetAll again.
+                    Assert.Throws<InvalidOperationException>(() => cursor.ToArray());
+                    Assert.Throws<InvalidOperationException>(() => cursor.GetAll());
+                }
+
+                // Partial iterator.
+                using (cursor = clientCache.Query(query))
+                {
+                    var item = cursor.First();
+                    Assert.AreEqual(item.Key.ToString(), item.Value.Name);
+                }
+
+                // Local.
+                query.Local = true;
+                var localRes = clientCache.Query(query).ToList();
+                Assert.Less(localRes.Count, cache.GetSize());
+            }
+        }
+
+        /// <summary>
+        /// Tests scan query with .NET filter.
+        /// </summary>
+        [Test]
+        public void TestWithFilter()
+        {
+            GetPersonCache();
+
+            using (var client = GetClient())
+            {
+                var clientCache = client.GetCache<int, Person>(CacheName);
+
+                // One result.
+                var single = clientCache.Query(new ScanQuery<int, Person>(new PersonFilter(x => x.Id == 3))).Single();
+                Assert.AreEqual(3, single.Key);
+
+                // Multiple results.
+                var res = clientCache.Query(new ScanQuery<int, Person>(new PersonFilter(x => x.Name.Length == 1)))
+                    .ToList();
+                Assert.AreEqual(9, res.Count);
+
+                // No results.
+                res = clientCache.Query(new ScanQuery<int, Person>(new PersonFilter(x => x == null))).ToList();
+                Assert.AreEqual(0, res.Count);
+            }
+        }
+
+        /// <summary>
+        /// Tests multiple cursors with the same client.
+        /// </summary>
+        [Test]
+        [SuppressMessage("ReSharper", "GenericEnumeratorNotDisposed")]
+        public void TestMultipleCursors()
+        {
+            var cache = GetPersonCache();
+
+            using (var client = GetClient())
+            {
+                var clientCache = client.GetCache<int, Person>(CacheName);
+
+                var qry = new ScanQuery<int, Person>();
+
+                var cur1 = clientCache.Query(qry).GetEnumerator();
+                var cur2 = clientCache.Query(qry).GetEnumerator();
+                var cur3 = clientCache.Query(qry).GetEnumerator();
+
+                // MaxCursors = 3
+                var ex = Assert.Throws<IgniteException>(() => clientCache.Query(qry));
+                Assert.AreEqual("Too many open cursors", ex.Message.Substring(0, 21));
+
+                var count = 0;
+
+                while (cur1.MoveNext())
+                {
+                    count++;
+
+                    Assert.IsTrue(cur2.MoveNext());
+                    Assert.IsTrue(cur3.MoveNext());
+
+                    Assert.AreEqual(cur1.Current.Key, cur2.Current.Key);
+                    Assert.AreEqual(cur1.Current.Key, cur3.Current.Key);
+                }
+
+                Assert.AreEqual(cache.GetSize(), count);
+
+                // Old cursors were auto-closed on last page, we can open new cursors now.
+                var c1 = clientCache.Query(qry);
+                var c2 = clientCache.Query(qry);
+                var c3 = clientCache.Query(qry);
+
+                Assert.Throws<IgniteException>(() => clientCache.Query(qry));
+
+                // Close one of the cursors.
+                c1.Dispose();
+                c1 = clientCache.Query(qry);
+                Assert.Throws<IgniteException>(() => clientCache.Query(qry));
+
+                // Close cursor via GetAll.
+                c1.GetAll();
+                c1 = clientCache.Query(qry);
+                Assert.Throws<IgniteException>(() => clientCache.Query(qry));
+
+                c1.Dispose();
+                c2.Dispose();
+                c3.Dispose();
+            }
+        }
+
+        /// <summary>
+        /// Gets the string cache.
+        /// </summary>
+        private static ICache<int, Person> GetPersonCache()
+        {
+            var cache = GetCache<Person>();
+
+            cache.RemoveAll();
+            cache.PutAll(Enumerable.Range(1, 10000).ToDictionary(x => x, x => new Person
+            {
+                Id = x,
+                Name = x.ToString()
+            }));
+
+            return cache;
+        }
+
+        /// <summary>
+        /// Person filter.
+        /// </summary>
+        private class PersonFilter : ICacheEntryFilter<int, Person>
+        {
+            /** Filter predicate. */
+            private readonly Func<Person, bool> _filter;
+
+            /// <summary>
+            /// Initializes a new instance of the <see cref="PersonFilter"/> class.
+            /// </summary>
+            /// <param name="filter">The filter.</param>
+            public PersonFilter(Func<Person, bool> filter)
+            {
+                Debug.Assert(filter != null);
+
+                _filter = filter;
+            }
+
+            /** <inheritdoc /> */
+            public bool Invoke(ICacheEntry<int, Person> entry)
+            {
+                return _filter(entry.Value);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/CacheTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/CacheTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/CacheTest.cs
deleted file mode 100644
index 3b0daa1..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/CacheTest.cs
+++ /dev/null
@@ -1,200 +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.Client
-{
-    using System;
-    using System.Collections.Concurrent;
-    using System.Collections.Generic;
-    using System.Linq;
-    using System.Threading;
-    using Apache.Ignite.Core.Binary;
-    using Apache.Ignite.Core.Cache;
-    using Apache.Ignite.Core.Client;
-    using NUnit.Framework;
-
-    /// <summary>
-    /// Thin client cache test.
-    /// </summary>
-    public sealed class CacheTest
-    {
-        /** Cache name. */
-        private const string CacheName = "cache";
-
-        /// <summary>
-        /// Fixture tear down.
-        /// </summary>
-        [TestFixtureSetUp]
-        public void FixtureSetUp()
-        {
-            Ignition.Start(TestUtils.GetTestConfiguration());
-        }
-
-        /// <summary>
-        /// Fixture tear down.
-        /// </summary>
-        [TestFixtureTearDown]
-        public void FixtureTearDown()
-        {
-            Ignition.StopAll(true);
-        }
-
-        /// <summary>
-        /// Tests the cache put / get with primitive data types.
-        /// </summary>
-        [Test]
-        public void TestPutGetPrimitives()
-        {
-            using (var client = GetClient())
-            {
-                GetCache<string>().Put(1, "foo");
-
-                var clientCache = client.GetCache<int?, string>(CacheName);
-
-                clientCache.Put(2, "bar");
-                clientCache[3] = "baz";
-
-                // Existing key.
-                Assert.AreEqual("foo", clientCache.Get(1));
-                Assert.AreEqual("foo", clientCache[1]);
-                Assert.AreEqual("bar", clientCache[2]);
-                Assert.AreEqual("baz", clientCache[3]);
-
-                // Missing key.
-                Assert.Throws<KeyNotFoundException>(() => clientCache.Get(-1));
-
-                // Null key.
-                Assert.Throws<ArgumentNullException>(() => clientCache.Get(null));
-            }
-        }
-
-        /// <summary>
-        /// Tests the cache put / get with user data types.
-        /// </summary>
-        [Test]
-        public void TestPutGetUserObjects([Values(true, false)] bool compactFooter)
-        {
-            var cfg = GetClientConfiguration();
-
-            cfg.BinaryConfiguration = new BinaryConfiguration
-            {
-                CompactFooter = compactFooter
-            };
-
-            using (var client = Ignition.StartClient(cfg))
-            {
-                var person = new Person {Id = 100, Name = "foo"};
-                var person2 = new Person2 {Id = 200, Name = "bar"};
-                
-                var serverCache = GetCache<Person>();
-                var clientCache = client.GetCache<int?, Person>(CacheName);
-
-                Assert.AreEqual(CacheName, clientCache.Name);
-
-                // Put through server cache.
-                serverCache.Put(1, person);
-
-                // Put through client cache.
-                clientCache.Put(2, person2);
-                clientCache[3] = person2;
-
-                // Read from client cache.
-                Assert.AreEqual("foo", clientCache.Get(1).Name);
-                Assert.AreEqual(100, clientCache[1].Id);
-                Assert.AreEqual(200, clientCache[2].Id);
-                Assert.AreEqual(200, clientCache[3].Id);
-
-                // Read from server cache.
-                Assert.AreEqual("foo", serverCache.Get(1).Name);
-                Assert.AreEqual(100, serverCache[1].Id);
-                Assert.AreEqual(200, serverCache[2].Id);
-                Assert.AreEqual(200, serverCache[3].Id);
-
-                // Null key or value.
-                Assert.Throws<ArgumentNullException>(() => clientCache.Put(10, null));
-                Assert.Throws<ArgumentNullException>(() => clientCache.Put(null, person));
-            }
-        }
-
-        /// <summary>
-        /// Tests client get in multiple threads with a single client.
-        /// </summary>
-        [Test]
-        [Category(TestUtils.CategoryIntensive)]
-        public void TestGetMultithreadedSingleClient()
-        {
-            GetCache<string>().Put(1, "foo");
-
-            using (var client = GetClient())
-            {
-                var clientCache = client.GetCache<int, string>(CacheName);
-
-                TestUtils.RunMultiThreaded(() => Assert.AreEqual("foo", clientCache.Get(1)),
-                    Environment.ProcessorCount, 5);
-            }
-        }
-
-        /// <summary>
-        /// Tests client get in multiple threads with multiple clients.
-        /// </summary>
-        [Test]
-        [Category(TestUtils.CategoryIntensive)]
-        public void TestGetMultithreadedMultiClient()
-        {
-            GetCache<string>().Put(1, "foo");
-
-            // One client per thread.
-            var clients = new ConcurrentDictionary<int, IIgniteClient>();
-
-            TestUtils.RunMultiThreaded(() =>
-                {
-                    var client = clients.GetOrAdd(Thread.CurrentThread.ManagedThreadId, _ => GetClient());
-
-                    var clientCache = client.GetCache<int, string>(CacheName);
-
-                    Assert.AreEqual("foo", clientCache.Get(1));
-                },
-                Environment.ProcessorCount, 5);
-
-            clients.ToList().ForEach(x => x.Value.Dispose());
-        }
-
-        /// <summary>
-        /// Gets the cache.
-        /// </summary>
-        private static ICache<int, T> GetCache<T>()
-        {
-            return Ignition.GetIgnite().GetOrCreateCache<int, T>(CacheName);
-        }
-
-        /// <summary>
-        /// Gets the client.
-        /// </summary>
-        private static IIgniteClient GetClient()
-        {
-            return Ignition.StartClient(GetClientConfiguration());
-        }
-
-        /// <summary>
-        /// Gets the client configuration.
-        /// </summary>
-        private static IgniteClientConfiguration GetClientConfiguration()
-        {
-            return new IgniteClientConfiguration {Host = "127.0.0.1"};
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/CacheTestNoMeta.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/CacheTestNoMeta.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/CacheTestNoMeta.cs
deleted file mode 100644
index a011583..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/CacheTestNoMeta.cs
+++ /dev/null
@@ -1,159 +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.Client
-{
-    using System.Collections.Generic;
-    using System.Linq;
-    using System.Net;
-    using Apache.Ignite.Core.Binary;
-    using Apache.Ignite.Core.Cache.Configuration;
-    using Apache.Ignite.Core.Cache.Query;
-    using Apache.Ignite.Core.Client;
-    using Apache.Ignite.Core.Impl.Binary;
-    using Apache.Ignite.Core.Impl.Binary.Metadata;
-    using NUnit.Framework;
-
-    /// <summary>
-    /// Client cache test without metadata (no-op binary processor).
-    /// </summary>
-    public class CacheTestNoMeta
-    {
-        /** Cache name. */
-        private const string CacheName = "cache";
-
-        /// <summary>
-        /// Fixture tear down.
-        /// </summary>
-        [TestFixtureSetUp]
-        public void FixtureSetUp()
-        {
-            Ignition.Start(TestUtils.GetTestConfiguration());
-        }
-
-        /// <summary>
-        /// Fixture tear down.
-        /// </summary>
-        [TestFixtureTearDown]
-        public void FixtureTearDown()
-        {
-            Ignition.StopAll(true);
-        }
-
-        /// <summary>
-        /// Tests the cache put / get with user data types.
-        /// </summary>
-        [Test]
-        public void TestPutGetUserObjects()
-        {
-            var cfg = new IgniteClientConfiguration
-            {
-                BinaryProcessor = new NoopBinaryProcessor(),
-                BinaryConfiguration = new BinaryConfiguration
-                {
-                    CompactFooter = false
-                },
-                Host = IPAddress.Loopback.ToString()
-            };
-
-            using (var client = Ignition.StartClient(cfg))
-            {
-                var serverCache = Ignition.GetIgnite().GetOrCreateCache<int?, Person>(
-                    new CacheConfiguration(CacheName, new QueryEntity
-                    {
-                        KeyType = typeof(int),
-                        ValueType = typeof(Person),
-                        Fields = new[]
-                        {
-                            new QueryField("id", typeof(int)),
-                            new QueryField("name", typeof(string))
-                        }
-                    }));
-
-                var clientCache = client.GetCache<int?, Person>(CacheName);
-
-                // Put through client cache.
-                clientCache.Put(1, new Person { Id = 100, Name = "foo" });
-                clientCache[2] = new Person { Id = 200, Name = "bar" };
-
-                // Read from client cache.
-                Assert.AreEqual("foo", clientCache.Get(1).Name);
-                Assert.AreEqual(100, clientCache[1].Id);
-                Assert.AreEqual(200, clientCache[2].Id);
-
-                // Read from server cache.
-                Assert.AreEqual("foo", serverCache.Get(1).Name);
-                Assert.AreEqual(100, serverCache[1].Id);
-                Assert.AreEqual(200, serverCache[2].Id);
-
-                // SQL from server cache.
-                var sqlRes = serverCache.Query(new SqlQuery(typeof(Person), "where id = 100")).GetAll().Single();
-                Assert.AreEqual(1, sqlRes.Key);
-                Assert.AreEqual(100, sqlRes.Value.Id);
-                Assert.AreEqual("foo", sqlRes.Value.Name);
-            }
-        }
-
-        /// <summary>
-        /// No-op binary processor (does not send meta to cluster).
-        /// </summary>
-        private class NoopBinaryProcessor : IBinaryProcessor
-        {
-            /** <inheritdoc /> */
-            public BinaryType GetBinaryType(int typeId)
-            {
-                return null;
-            }
-
-            /** <inheritdoc /> */
-            public List<IBinaryType> GetBinaryTypes()
-            {
-                return null;
-            }
-
-            /** <inheritdoc /> */
-            public int[] GetSchema(int typeId, int schemaId)
-            {
-                return null;
-            }
-
-            /** <inheritdoc /> */
-            public void PutBinaryTypes(ICollection<BinaryType> types)
-            {
-                // No-op.
-            }
-
-            /** <inheritdoc /> */
-            public bool RegisterType(int id, string typeName)
-            {
-                return false;
-            }
-
-            /** <inheritdoc /> */
-            public BinaryType RegisterEnum(string typeName, IEnumerable<KeyValuePair<string, int>> values)
-            {
-                return null;
-            }
-
-            /** <inheritdoc /> */
-            public string GetTypeName(int id)
-            {
-                return null;
-            }
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
new file mode 100644
index 0000000..81e1418
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
@@ -0,0 +1,113 @@
+/*
+ * 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.Client
+{
+    using System.Net;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Client;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Base class for client tests.
+    /// </summary>
+    public class ClientTestBase
+    {
+        /** Cache name. */
+        protected const string CacheName = "cache";
+
+        /** Grid count. */
+        private readonly int _gridCount = 1;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ClientTestBase"/> class.
+        /// </summary>
+        public ClientTestBase()
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ClientTestBase"/> class.
+        /// </summary>
+        public ClientTestBase(int gridCount)
+        {
+            _gridCount = gridCount;
+        }
+
+        /// <summary>
+        /// Fixture tear down.
+        /// </summary>
+        [TestFixtureSetUp]
+        public void FixtureSetUp()
+        {
+            var cfg = GetIgniteConfiguration();
+            Ignition.Start(cfg);
+
+            cfg.AutoGenerateIgniteInstanceName = true;
+
+            for (var i = 1; i < _gridCount; i++)
+            {
+                Ignition.Start(cfg);
+            }
+        }
+
+        /// <summary>
+        /// Fixture tear down.
+        /// </summary>
+        [TestFixtureTearDown]
+        public void FixtureTearDown()
+        {
+            Ignition.StopAll(true);
+        }
+
+        /// <summary>
+        /// Gets the cache.
+        /// </summary>
+        protected static ICache<int, T> GetCache<T>()
+        {
+            return Ignition.GetIgnite().GetOrCreateCache<int, T>(CacheName);
+        }
+
+        /// <summary>
+        /// Gets the client.
+        /// </summary>
+        protected IIgniteClient GetClient()
+        {
+            return Ignition.StartClient(GetClientConfiguration());
+        }
+
+        /// <summary>
+        /// Gets the client configuration.
+        /// </summary>
+        protected IgniteClientConfiguration GetClientConfiguration()
+        {
+            return new IgniteClientConfiguration
+            {
+                Host = IPAddress.Loopback.ToString()
+            };
+        }
+
+        /// <summary>
+        /// Gets the Ignite configuration.
+        /// </summary>
+        protected virtual IgniteConfiguration GetIgniteConfiguration()
+        {
+            return TestUtils.GetTestConfiguration();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Person.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Person.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Person.cs
deleted file mode 100644
index 7f0309f..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Person.cs
+++ /dev/null
@@ -1,48 +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.Client
-{
-    /// <summary>
-    /// Test person.
-    /// </summary>
-    public class Person
-    {
-        /// <summary>
-        /// Gets or sets the identifier.
-        /// </summary>
-        public int Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the parent.
-        /// </summary>
-        public Person Parent { get;set; }
-    }
-
-    /// <summary>
-    /// Test person 2.
-    /// </summary>
-    public class Person2 : Person
-    {
-        // No-op.
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSocketTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSocketTest.cs
index 9e2200f..48bd3dd 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSocketTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSocketTest.cs
@@ -81,6 +81,9 @@ namespace Apache.Ignite.Core.Tests.Client
                     var requestId = reader.ReadLong();
                     Assert.AreEqual(1, requestId);
 
+                    var success = reader.ReadBoolean();
+                    Assert.IsTrue(success);
+
                     var res = reader.ReadObject<string>();
                     Assert.AreEqual(cache[1], res);
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 615ce90..ed34675 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -103,6 +103,8 @@
     <Compile Include="Common\ExceptionFactory.cs" />
     <Compile Include="Configuration\Package-Info.cs" />
     <Compile Include="Impl\Binary\BinaryTypeId.cs" />
+    <Compile Include="Impl\Client\Cache\CacheFlags.cs" />
+    <Compile Include="Impl\Client\Cache\Query\ClientQueryCursor.cs" />
     <Compile Include="Impl\Cache\Query\PlatformQueryQursorBase.cs" />
     <Compile Include="Impl\Binary\BinaryProcessorClient.cs" />
     <Compile Include="Impl\Binary\IBinaryProcessor.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/ScanQuery.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/ScanQuery.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/ScanQuery.cs
index 2c9cf35..bb9852d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/ScanQuery.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/ScanQuery.cs
@@ -52,7 +52,7 @@ namespace Apache.Ignite.Core.Cache.Query
             writer.WriteInt(PageSize);
             
             writer.WriteBoolean(Partition.HasValue);
-            
+
             if (Partition.HasValue)
                 writer.WriteInt(Partition.Value);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
index b8bd6fe..edd411c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
@@ -18,6 +18,8 @@
 namespace Apache.Ignite.Core.Client.Cache
 {
     using System.Collections.Generic;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Cache.Query;
 
     /// <summary>
     /// Client cache API. See <see cref="IIgniteClient.GetCache{K, V}"/>.
@@ -56,5 +58,12 @@ namespace Apache.Ignite.Core.Client.Cache
         /// <returns>Cache value with the specified key.</returns>
         /// <exception cref="KeyNotFoundException">If the key is not present in the cache.</exception>
         TV this[TK key] { get; set; }
+
+        /// <summary>
+        /// Executes a Scan query.
+        /// </summary>
+        /// <param name="scanQuery">Scan query.</param>
+        /// <returns>Query cursor.</returns>
+        IQueryCursor<ICacheEntry<TK, TV>> Query(ScanQuery<TK, TV> scanQuery);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs
index 418bb24..8f00a2e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs
@@ -54,35 +54,45 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
         /** Disposed flag. */
         private volatile bool _disposed;
 
+        /** Whether next batch is available. */
+        private bool _hasNext = true;
+
         /// <summary>
         /// Constructor.
         /// </summary>
         /// <param name="marsh">Marshaller.</param>
         /// <param name="keepBinary">Keep binary flag.</param>
-        protected QueryCursorBase(Marshaller marsh, bool keepBinary)
+        /// <param name="initialBatchStream">Optional stream with initial batch.</param>
+        protected QueryCursorBase(Marshaller marsh, bool keepBinary, IBinaryStream initialBatchStream = null)
         {
             Debug.Assert(marsh != null);
 
             _keepBinary = keepBinary;
             _marsh = marsh;
+
+            if (initialBatchStream != null)
+            {
+                _batch = ConvertGetBatch(initialBatchStream);
+            }
         }
 
         /** <inheritdoc /> */
         public IList<T> GetAll()
         {
-            ThrowIfDisposed();
+            if (_getAllCalled)
+                throw new InvalidOperationException("Failed to get all entries because GetAll() " +
+                                                    "method has already been called.");
 
             if (_iterCalled)
-                throw new InvalidOperationException("Failed to get all entries because GetEnumerator() " + 
-                    "method has already been called.");
+                throw new InvalidOperationException("Failed to get all entries because GetEnumerator() " +
+                                                    "method has already been called.");
 
-            if (_getAllCalled)
-                throw new InvalidOperationException("Failed to get all entries because GetAll() " + 
-                    "method has already been called.");
+            ThrowIfDisposed();
 
             var res = GetAllInternal();
 
             _getAllCalled = true;
+            _hasNext = false;
 
             return res;
         }
@@ -92,20 +102,20 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
         /** <inheritdoc /> */
         public IEnumerator<T> GetEnumerator()
         {
-            ThrowIfDisposed();
-
-            if (_iterCalled)
+            if (_getAllCalled)
             {
                 throw new InvalidOperationException("Failed to get enumerator entries because " +
-                                                    "GetEnumerator() method has already been called.");
+                                                    "GetAll() method has already been called.");
             }
 
-            if (_getAllCalled)
+            if (_iterCalled)
             {
                 throw new InvalidOperationException("Failed to get enumerator entries because " +
-                                                    "GetAll() method has already been called.");
+                                                    "GetEnumerator() method has already been called.");
             }
 
+            ThrowIfDisposed();
+
             InitIterator();
 
             _iterCalled = true;
@@ -196,7 +206,7 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
         /// </summary>
         private void RequestBatch()
         {
-            _batch = GetBatch();
+            _batch = _hasNext ? GetBatch() : null;
 
             _batchPos = 0;
         }
@@ -237,12 +247,19 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
             var size = reader.ReadInt();
 
             if (size == 0)
+            {
+                _hasNext = false;
                 return null;
+            }
 
             var res = new T[size];
 
             for (var i = 0; i < size; i++)
+            {
                 res[i] = Read(reader);
+            }
+
+            _hasNext = stream.ReadBool();
 
             return res;
         }
@@ -253,9 +270,14 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
             lock (this)
             {
                 if (_disposed)
+                {
                     return;
+                }
 
-                Dispose(true);
+                if (_hasNext)
+                {
+                    Dispose(true);
+                }
 
                 GC.SuppressFinalize(this);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
index affa815..974bab3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
@@ -21,11 +21,15 @@ namespace Apache.Ignite.Core.Impl.Client.Cache
     using System.Collections.Generic;
     using System.Diagnostics;
     using System.IO;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Cache.Query;
     using Apache.Ignite.Core.Client;
     using Apache.Ignite.Core.Client.Cache;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Binary.IO;
+    using Apache.Ignite.Core.Impl.Cache;
     using Apache.Ignite.Core.Impl.Client;
+    using Apache.Ignite.Core.Impl.Client.Cache.Query;
     using Apache.Ignite.Core.Impl.Common;
     using BinaryWriter = Apache.Ignite.Core.Impl.Binary.BinaryWriter;
 
@@ -34,6 +38,9 @@ namespace Apache.Ignite.Core.Impl.Client.Cache
     /// </summary>
     internal class CacheClient<TK, TV> : ICacheClient<TK, TV>
     {
+        /** Scan query filter platform code: .NET filter. */
+        private const byte FilterPlatformDotnet = 2;
+
         /** Cache name. */
         private readonly string _name;
 
@@ -46,6 +53,9 @@ namespace Apache.Ignite.Core.Impl.Client.Cache
         /** Marshaller. */
         private readonly Marshaller _marsh;
 
+        /** Keep binary flag. */
+        private bool _keepBinary = false;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="CacheClient{TK, TV}" /> class.
         /// </summary>
@@ -102,6 +112,17 @@ namespace Apache.Ignite.Core.Impl.Client.Cache
             });
         }
 
+        /** <inheritDoc /> */
+        public IQueryCursor<ICacheEntry<TK, TV>> Query(ScanQuery<TK, TV> scanQuery)
+        {
+            IgniteArgumentCheck.NotNull(scanQuery, "query");
+
+            // Filter is a binary object for all platforms.
+            // For .NET it is a CacheEntryFilterHolder with a predefined id (BinaryTypeId.CacheEntryPredicateHolder).
+            return DoOutInOp(ClientOp.QueryScan, w => WriteScanQuery(w, scanQuery),
+                s => new ClientQueryCursor<TK, TV>(_ignite, s.ReadLong(), _keepBinary, s));
+        }
+
         /// <summary>
         /// Does the out in op.
         /// </summary>
@@ -150,6 +171,34 @@ namespace Apache.Ignite.Core.Impl.Client.Cache
         }
 
         /// <summary>
+        /// Writes the scan query.
+        /// </summary>
+        private void WriteScanQuery(BinaryWriter writer, ScanQuery<TK, TV> qry)
+        {
+            Debug.Assert(qry != null);
+
+            if (qry.Filter == null)
+            {
+                writer.WriteByte(BinaryUtils.HdrNull);
+            }
+            else
+            {
+                var holder = new CacheEntryFilterHolder(qry.Filter, (key, val) => qry.Filter.Invoke(
+                    new CacheEntry<TK, TV>((TK)key, (TV)val)), writer.Marshaller, _keepBinary);
+
+                writer.WriteObject(holder);
+
+                writer.WriteByte(FilterPlatformDotnet);
+            }
+
+            writer.WriteInt(qry.PageSize);
+
+            writer.WriteInt(qry.Partition ?? -1);
+
+            writer.WriteBoolean(qry.Local);
+        }
+
+        /// <summary>
         /// Gets the key not found exception.
         /// </summary>
         private static KeyNotFoundException GetKeyNotFoundException()

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheFlags.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheFlags.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheFlags.cs
new file mode 100644
index 0000000..e24d952
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheFlags.cs
@@ -0,0 +1,38 @@
+/*
+ * 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.Impl.Client.Cache
+{
+    using System;
+
+    /// <summary>
+    /// Cache operation flags.
+    /// </summary>
+    [Flags]
+    internal enum CacheFlags : byte
+    {
+        /// <summary>
+        /// No flags.
+        /// </summary>
+        None = 0x00,
+
+        /// <summary>
+        /// Keep binary.
+        /// </summary>
+        KeepBinary = 0x01
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursor.cs
new file mode 100644
index 0000000..898bbbe
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursor.cs
@@ -0,0 +1,94 @@
+/*
+ * 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.Impl.Client.Cache.Query
+{
+    using System.Collections.Generic;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+    using Apache.Ignite.Core.Impl.Cache;
+    using Apache.Ignite.Core.Impl.Cache.Query;
+    using Apache.Ignite.Core.Impl.Client;
+
+    /// <summary>
+    /// Client query cursor.
+    /// </summary>
+    internal class ClientQueryCursor<TK, TV> : QueryCursorBase<ICacheEntry<TK, TV>>
+    {
+        /** Ignite. */
+        private readonly IgniteClient _ignite;
+
+        /** Cursor ID. */
+        private readonly long _cursorId;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ClientQueryCursor{TK, TV}" /> class.
+        /// </summary>
+        /// <param name="ignite">The ignite.</param>
+        /// <param name="cursorId">The cursor identifier.</param>
+        /// <param name="keepBinary">Keep binary flag.</param>
+        /// <param name="initialBatchStream">Optional stream with initial batch.</param>
+        public ClientQueryCursor(IgniteClient ignite, long cursorId, bool keepBinary, 
+            IBinaryStream initialBatchStream) 
+            : base(ignite.Marshaller, keepBinary, initialBatchStream)
+        {
+            _ignite = ignite;
+            _cursorId = cursorId;
+        }
+
+        /** <inheritdoc /> */
+        protected override void InitIterator()
+        {
+            // No-op.
+        }
+
+        /** <inheritdoc /> */
+        protected override IList<ICacheEntry<TK, TV>> GetAllInternal()
+        {
+            return this.ToArray();
+        }
+
+        /** <inheritdoc /> */
+        protected override ICacheEntry<TK, TV> Read(BinaryReader reader)
+        {
+            return new CacheEntry<TK, TV>(reader.ReadObject<TK>(), reader.ReadObject<TV>());
+        }
+
+        /** <inheritdoc /> */
+        protected override ICacheEntry<TK, TV>[] GetBatch()
+        {
+            return _ignite.Socket.DoOutInOp(ClientOp.QueryScanCursorGetPage,
+                w => w.WriteLong(_cursorId),
+                s => ConvertGetBatch(s));
+        }
+
+        /** <inheritdoc /> */
+        protected override void Dispose(bool disposing)
+        {
+            try
+            {
+                _ignite.Socket.DoOutInOp<object>(ClientOp.ResourceClose, w => w.WriteLong(_cursorId), null);
+            }
+            finally
+            {
+                base.Dispose(disposing);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
index 79d7c9e..c39b68f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
@@ -27,6 +27,9 @@ namespace Apache.Ignite.Core.Impl.Client
         BinaryTypeGet = 3,
         CachePut = 4,
         BinaryTypeNamePut = 5,
-        BinaryTypePut = 6
+        BinaryTypePut = 6,
+        QueryScan = 7,
+        QueryScanCursorGetPage = 8,
+        ResourceClose = 9
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs
index 0204ef8..1a245a1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs
@@ -88,6 +88,12 @@ namespace Apache.Ignite.Core.Impl.Client
                 var resRequestId = stream.ReadLong();
                 Debug.Assert(requestId == resRequestId);
 
+                if (!stream.ReadBool())
+                {
+                    // Error.
+                    throw new IgniteException(BinaryUtils.Marshaller.StartUnmarshal(stream).ReadString());
+                }
+
                 if (readFunc != null)
                 {
                     return readFunc(stream);
@@ -159,7 +165,11 @@ namespace Apache.Ignite.Core.Impl.Client
                     
                     buf = new byte[size];
                     received = sock.Receive(buf);
-                    Debug.Assert(received == buf.Length);
+
+                    while (received < size)
+                    {
+                        received += sock.Receive(buf, received, size - received, SocketFlags.None);
+                    }
 
                     return buf;
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/86372dee/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs
index 29b8a2c..d05355a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs
@@ -144,9 +144,16 @@ namespace Apache.Ignite.Core.Impl.Client
         /// <summary>
         /// Gets the client not supported exception.
         /// </summary>
-        private static NotSupportedException GetClientNotSupportedException()
+        public static NotSupportedException GetClientNotSupportedException(string info = null)
         {
-            return new NotSupportedException("Operation is not supported in thin client mode.");
+            var msg = "Operation is not supported in thin client mode.";
+
+            if (info != null)
+            {
+                msg += " " + info;
+            }
+
+            return new NotSupportedException(msg);
         }
     }
 }


Mime
View raw message