IGNITE-6336 .NET: Thin client: Create cache

This closes #2935


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

Branch: refs/heads/ignite-zk
Commit: 52b46c35fb4bf4f2b96bdc10673563843502fcbe
Parents: af6b933
Author: Pavel Tupitsyn <ptupit...@apache.org>
Authored: Thu Nov 16 11:22:46 2017 +0300
Committer: Pavel Tupitsyn <ptupit...@apache.org>
Committed: Thu Nov 16 11:22:46 2017 +0300

----------------------------------------------------------------------
 .../configuration/CacheConfiguration.java       |   5 +-
 .../platform/client/ClientMessageParser.java    |  49 +++
 .../platform/client/ClientStatus.java           |   3 +
 .../ClientCacheConfigurationSerializer.java     | 180 ++++++++
 ...ientCacheCreateWithConfigurationRequest.java |  58 +++
 .../cache/ClientCacheCreateWithNameRequest.java |  56 +++
 .../client/cache/ClientCacheDestroyRequest.java |  49 +++
 .../ClientCacheGetConfigurationRequest.java     |  47 +++
 .../ClientCacheGetConfigurationResponse.java    |  51 +++
 .../cache/ClientCacheGetNamesRequest.java       |  46 ++
 .../cache/ClientCacheGetNamesResponse.java      |  56 +++
 ...acheGetOrCreateWithConfigurationRequest.java |  58 +++
 .../ClientCacheGetOrCreateWithNameRequest.java  |  49 +++
 .../utils/PlatformConfigurationUtils.java       |  24 +-
 .../Apache.Ignite.Core.Tests.csproj             |   2 +
 .../Cache/CacheConfigurationTest.cs             |   2 +-
 .../Cache/ClientCacheConfigurationTest.cs       | 211 ++++++++++
 .../Client/Cache/CreateCacheTest.cs             | 209 +++++++++
 .../Client/ClientTestBase.cs                    |   7 +
 .../IgniteConfigurationTest.cs                  |   2 +
 .../Apache.Ignite.Core.csproj                   |   2 +
 .../Cache/Configuration/QueryEntity.cs          |  10 +-
 .../Client/Cache/CacheClientConfiguration.cs    | 420 +++++++++++++++++++
 .../Client/Cache/ICacheClient.cs                |   5 +
 .../Apache.Ignite.Core/Client/IIgniteClient.cs  |  50 +++
 .../dotnet/Apache.Ignite.Core/IIgnite.cs        |   1 -
 .../Impl/Binary/BinaryReaderExtensions.cs       |  18 +
 .../Impl/Client/Cache/CacheClient.cs            |   6 +
 .../Cache/ClientCacheConfigurationSerializer.cs | 261 ++++++++++++
 .../Apache.Ignite.Core/Impl/Client/ClientOp.cs  |   9 +-
 .../Impl/Client/ClientStatus.cs                 |   1 +
 .../Impl/Client/IgniteClient.cs                 |  85 ++++
 .../examples/Apache.Ignite.Examples/App.config  |   4 -
 .../ThinClient/ThinClientPutGetExample.cs       |   5 +-
 .../ThinClient/ThinClientQueryExample.cs        |   4 +-
 35 files changed, 2010 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
 
b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
index aeb1b2f..7d2730c 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
@@ -1711,8 +1711,9 @@ public class CacheConfiguration<K, V> extends 
MutableConfiguration<K, V> {
      * @return {@code this} for chaining.
      */
     public CacheConfiguration<K, V> setSqlSchema(String sqlSchema) {
-        A.ensure((sqlSchema != null), "Schema could not be null.");
-        A.ensure(!sqlSchema.isEmpty(), "Schema could not be empty.");
+        if (sqlSchema != null) {
+            A.ensure(!sqlSchema.isEmpty(), "Schema could not be empty.");
+        }
 
         this.sqlSchema = sqlSchema;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
index f0f0f4c..4ad6a90 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
@@ -37,11 +37,18 @@ import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheCl
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheClearRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheContainsKeyRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheContainsKeysRequest;
+import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheCreateWithConfigurationRequest;
+import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheCreateWithNameRequest;
+import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheDestroyRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAllRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAndPutIfAbsentRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAndPutRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAndRemoveRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAndReplaceRequest;
+import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetConfigurationRequest;
+import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetNamesRequest;
+import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetOrCreateWithConfigurationRequest;
+import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetOrCreateWithNameRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetSizeRequest;
 import 
org.apache.ignite.internal.processors.platform.client.cache.ClientCachePutAllRequest;
@@ -144,6 +151,27 @@ public class ClientMessageParser implements 
ClientListenerMessageParser {
     /** */
     private static final short OP_CACHE_REMOVE_ALL = 28;
 
+    /** */
+    private static final short OP_CACHE_CREATE_WITH_NAME = 29;
+
+    /** */
+    private static final short OP_CACHE_GET_OR_CREATE_WITH_NAME = 30;
+
+    /** */
+    private static final short OP_CACHE_DESTROY = 31;
+
+    /** */
+    private static final short OP_CACHE_GET_NAMES = 32;
+
+    /** */
+    private static final short OP_CACHE_GET_CONFIGURATION = 33;
+
+    /** */
+    private static final short OP_CACHE_CREATE_WITH_CONFIGURATION = 34;
+
+    /** */
+    private static final short OP_CACHE_GET_OR_CREATE_WITH_CONFIGURATION = 35;
+
     /** Marshaller. */
     private final GridBinaryMarshaller marsh;
 
@@ -262,6 +290,27 @@ public class ClientMessageParser implements 
ClientListenerMessageParser {
 
             case OP_CACHE_REMOVE_ALL:
                 return new ClientCacheRemoveAllRequest(reader);
+
+            case OP_CACHE_CREATE_WITH_NAME:
+                return new ClientCacheCreateWithNameRequest(reader);
+
+            case OP_CACHE_GET_OR_CREATE_WITH_NAME:
+                return new ClientCacheGetOrCreateWithNameRequest(reader);
+
+            case OP_CACHE_DESTROY:
+                return new ClientCacheDestroyRequest(reader);
+
+            case OP_CACHE_GET_NAMES:
+                return new ClientCacheGetNamesRequest(reader);
+
+            case OP_CACHE_GET_CONFIGURATION:
+                return new ClientCacheGetConfigurationRequest(reader);
+
+            case OP_CACHE_CREATE_WITH_CONFIGURATION:
+                return new ClientCacheCreateWithConfigurationRequest(reader);
+
+            case OP_CACHE_GET_OR_CREATE_WITH_CONFIGURATION:
+                return new 
ClientCacheGetOrCreateWithConfigurationRequest(reader);
         }
 
         return new ClientRawRequest(reader.readLong(), 
ClientStatus.INVALID_OP_CODE,

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java
index 0f374ff..4f55072 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java
@@ -40,6 +40,9 @@ public final class ClientStatus {
     /** Cache does not exist. */
     public static final int CACHE_DOES_NOT_EXIST = 1000;
 
+    /** Cache already exists. */
+    public static final int CACHE_EXISTS = 1001;
+
     /** Too many cursors. */
     public static final int TOO_MANY_CURSORS = 1010;
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
new file mode 100644
index 0000000..0f28b81
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheKeyConfiguration;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheRebalanceMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.PartitionLossPolicy;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import static 
org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils.readQueryEntity;
+import static 
org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils.writeEnumInt;
+import static 
org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils.writeQueryEntity;
+
+/**
+ * Cache configuration serializer.
+ */
+public class ClientCacheConfigurationSerializer {
+    /**
+     * Writes the cache configuration.
+     * @param writer Writer.
+     * @param cfg Configuration.
+     */
+    static void write(BinaryRawWriterEx writer, CacheConfiguration cfg) {
+        assert writer != null;
+        assert cfg != null;
+
+        // Reserve for length.
+        int pos = writer.reserveInt();
+
+        writeEnumInt(writer, cfg.getAtomicityMode(), 
CacheConfiguration.DFLT_CACHE_ATOMICITY_MODE);
+        writer.writeInt(cfg.getBackups());
+        writeEnumInt(writer, cfg.getCacheMode(), 
CacheConfiguration.DFLT_CACHE_MODE);
+        writer.writeBoolean(cfg.isCopyOnRead());
+        writer.writeString(cfg.getDataRegionName());
+        writer.writeBoolean(cfg.isEagerTtl());
+        writer.writeBoolean(cfg.isStatisticsEnabled());
+        writer.writeString(cfg.getGroupName());
+        writer.writeBoolean(cfg.isInvalidate());
+        writer.writeLong(cfg.getDefaultLockTimeout());
+        writer.writeInt(cfg.getMaxConcurrentAsyncOperations());
+        writer.writeInt(cfg.getMaxQueryIteratorsCount());
+        writer.writeString(cfg.getName());
+        writer.writeBoolean(cfg.isOnheapCacheEnabled());
+        writer.writeInt(cfg.getPartitionLossPolicy().ordinal());
+        writer.writeInt(cfg.getQueryDetailMetricsSize());
+        writer.writeInt(cfg.getQueryParallelism());
+        writer.writeBoolean(cfg.isReadFromBackup());
+        writer.writeInt(cfg.getRebalanceBatchSize());
+        writer.writeLong(cfg.getRebalanceBatchesPrefetchCount());
+        writer.writeLong(cfg.getRebalanceDelay());
+        writeEnumInt(writer, cfg.getRebalanceMode(), 
CacheConfiguration.DFLT_REBALANCE_MODE);
+        writer.writeInt(cfg.getRebalanceOrder());
+        writer.writeLong(cfg.getRebalanceThrottle());
+        writer.writeLong(cfg.getRebalanceTimeout());
+        writer.writeBoolean(cfg.isSqlEscapeAll());
+        writer.writeInt(cfg.getSqlIndexMaxInlineSize());
+        writer.writeString(cfg.getSqlSchema());
+        writeEnumInt(writer, cfg.getWriteSynchronizationMode());
+
+        CacheKeyConfiguration[] keys = cfg.getKeyConfiguration();
+
+        if (keys != null) {
+            writer.writeInt(keys.length);
+
+            for (CacheKeyConfiguration key : keys) {
+                writer.writeString(key.getTypeName());
+                writer.writeString(key.getAffinityKeyFieldName());
+            }
+        } else {
+            writer.writeInt(0);
+        }
+
+        //noinspection unchecked
+        Collection<QueryEntity> qryEntities = cfg.getQueryEntities();
+
+        if (qryEntities != null) {
+            writer.writeInt(qryEntities.size());
+
+            for (QueryEntity e : qryEntities)
+                writeQueryEntity(writer, e);
+        } else
+            writer.writeInt(0);
+
+        // Write length (so that part of the config can be skipped).
+        writer.writeInt(pos, writer.out().position() - pos - 4);
+    }
+
+    /**
+     * Reads the cache configuration.
+     *
+     * @param reader Reader.
+     * @return Configuration.
+     */
+    static CacheConfiguration read(BinaryRawReader reader) {
+        reader.readInt();  // Skip length.
+
+        CacheConfiguration cfg = new CacheConfiguration()
+                
.setAtomicityMode(CacheAtomicityMode.fromOrdinal(reader.readInt()))
+                .setBackups(reader.readInt())
+                .setCacheMode(CacheMode.fromOrdinal(reader.readInt()))
+                .setCopyOnRead(reader.readBoolean())
+                .setDataRegionName(reader.readString())
+                .setEagerTtl(reader.readBoolean())
+                .setStatisticsEnabled(reader.readBoolean())
+                .setGroupName(reader.readString())
+                .setInvalidate(reader.readBoolean())
+                .setDefaultLockTimeout(reader.readLong())
+                .setMaxConcurrentAsyncOperations(reader.readInt())
+                .setMaxQueryIteratorsCount(reader.readInt())
+                .setName(reader.readString())
+                .setOnheapCacheEnabled(reader.readBoolean())
+                
.setPartitionLossPolicy(PartitionLossPolicy.fromOrdinal((byte)reader.readInt()))
+                .setQueryDetailMetricsSize(reader.readInt())
+                .setQueryParallelism(reader.readInt())
+                .setReadFromBackup(reader.readBoolean())
+                .setRebalanceBatchSize(reader.readInt())
+                .setRebalanceBatchesPrefetchCount(reader.readLong())
+                .setRebalanceDelay(reader.readLong())
+                
.setRebalanceMode(CacheRebalanceMode.fromOrdinal(reader.readInt()))
+                .setRebalanceOrder(reader.readInt())
+                .setRebalanceThrottle(reader.readLong())
+                .setRebalanceTimeout(reader.readLong())
+                .setSqlEscapeAll(reader.readBoolean())
+                .setSqlIndexMaxInlineSize(reader.readInt())
+                .setSqlSchema(reader.readString())
+                
.setWriteSynchronizationMode(CacheWriteSynchronizationMode.fromOrdinal(reader.readInt()));
+
+        // Key configuration.
+        int keyCnt = reader.readInt();
+
+        if (keyCnt > 0) {
+            CacheKeyConfiguration[] keys = new CacheKeyConfiguration[keyCnt];
+
+            for (int i = 0; i < keyCnt; i++) {
+                keys[i] = new CacheKeyConfiguration(reader.readString(), 
reader.readString());
+            }
+
+            cfg.setKeyConfiguration(keys);
+        }
+
+        // Query entities.
+        int qryEntCnt = reader.readInt();
+
+        if (qryEntCnt > 0) {
+            Collection<QueryEntity> entities = new ArrayList<>(qryEntCnt);
+
+            for (int i = 0; i < qryEntCnt; i++)
+                entities.add(readQueryEntity(reader));
+
+            cfg.setQueryEntities(entities);
+        }
+
+        return cfg;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
new file mode 100644
index 0000000..4b4dcec
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.cache.CacheExistsException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+import org.apache.ignite.internal.processors.platform.client.ClientStatus;
+import 
org.apache.ignite.internal.processors.platform.client.IgniteClientException;
+
+/**
+ * Cache create with configuration request.
+ */
+@SuppressWarnings("unchecked")
+public class ClientCacheCreateWithConfigurationRequest extends ClientRequest {
+    /** Cache configuration. */
+    private final CacheConfiguration cacheCfg;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheCreateWithConfigurationRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cacheCfg = ClientCacheConfigurationSerializer.read(reader);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        try {
+            ctx.kernalContext().grid().createCache(cacheCfg);
+        } catch (CacheExistsException e) {
+            throw new IgniteClientException(ClientStatus.CACHE_EXISTS, 
e.getMessage());
+        }
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithNameRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithNameRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithNameRequest.java
new file mode 100644
index 0000000..9155d76
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithNameRequest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.cache.CacheExistsException;
+import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+import org.apache.ignite.internal.processors.platform.client.ClientStatus;
+import 
org.apache.ignite.internal.processors.platform.client.IgniteClientException;
+
+/**
+ * Cache create with name request.
+ */
+public class ClientCacheCreateWithNameRequest extends ClientRequest {
+    /** Cache name. */
+    private final String cacheName;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheCreateWithNameRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cacheName = reader.readString();
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        try {
+            ctx.kernalContext().grid().createCache(cacheName);
+        } catch (CacheExistsException e) {
+            throw new IgniteClientException(ClientStatus.CACHE_EXISTS, 
e.getMessage());
+        }
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheDestroyRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheDestroyRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheDestroyRequest.java
new file mode 100644
index 0000000..032116d
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheDestroyRequest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Cache destroy request.
+ */
+public class ClientCacheDestroyRequest extends ClientRequest {
+    /** Cache name. */
+    private final String cacheName;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheDestroyRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cacheName = reader.readString();
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        ctx.kernalContext().grid().destroyCache(cacheName);
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
new file mode 100644
index 0000000..3632095
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.configuration.CacheConfiguration;
+import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Cache configuration request.
+ */
+public class ClientCacheGetConfigurationRequest extends ClientCacheRequest {
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheGetConfigurationRequest(BinaryRawReader reader) {
+        super(reader);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        CacheConfiguration cfg = ((IgniteCache<Object, Object>) rawCache(ctx))
+                .getConfiguration(CacheConfiguration.class);
+
+        return new ClientCacheGetConfigurationResponse(requestId(), cfg);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
new file mode 100644
index 0000000..2033dfe
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Cache configuration response.
+ */
+public class ClientCacheGetConfigurationResponse extends ClientResponse {
+    /** Cache configuration. */
+    private final CacheConfiguration cfg;
+
+    /**
+     * Constructor.
+     *
+     * @param reqId Request id.
+     * @param cfg Cache configuration.
+     */
+    ClientCacheGetConfigurationResponse(long reqId, CacheConfiguration cfg) {
+        super(reqId);
+
+        assert cfg != null;
+
+        this.cfg = cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void encode(BinaryRawWriterEx writer) {
+        super.encode(writer);
+
+        ClientCacheConfigurationSerializer.write(writer, cfg);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesRequest.java
new file mode 100644
index 0000000..376fcc1
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesRequest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+import java.util.Collection;
+
+/**
+ * Cache names request.
+ */
+public class ClientCacheGetNamesRequest extends ClientRequest {
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheGetNamesRequest(BinaryRawReader reader) {
+        super(reader);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        Collection<String> names = ctx.kernalContext().grid().cacheNames();
+
+        return new ClientCacheGetNamesResponse(requestId(), names);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesResponse.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesResponse.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesResponse.java
new file mode 100644
index 0000000..6266515
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesResponse.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+import java.util.Collection;
+
+/**
+ * Cache names response.
+ */
+public class ClientCacheGetNamesResponse extends ClientResponse {
+    /** Cache names. */
+    private final Collection<String> cacheNames;
+
+    /**
+     * Constructor.
+     *
+     * @param reqId Request id.
+     * @param cacheNames Cache names.
+     */
+    ClientCacheGetNamesResponse(long reqId, Collection<String> cacheNames) {
+        super(reqId);
+
+        assert cacheNames != null;
+
+        this.cacheNames = cacheNames;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void encode(BinaryRawWriterEx writer) {
+        super.encode(writer);
+
+        writer.writeInt(cacheNames.size());
+
+        for (String name : cacheNames) {
+            writer.writeString(name);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
new file mode 100644
index 0000000..267318a
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.cache.CacheExistsException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+import org.apache.ignite.internal.processors.platform.client.ClientStatus;
+import 
org.apache.ignite.internal.processors.platform.client.IgniteClientException;
+
+/**
+ * Cache get or create with configuration request.
+ */
+@SuppressWarnings("unchecked")
+public class ClientCacheGetOrCreateWithConfigurationRequest extends 
ClientRequest {
+    /** Cache configuration. */
+    private final CacheConfiguration cacheCfg;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheGetOrCreateWithConfigurationRequest(BinaryRawReader 
reader) {
+        super(reader);
+
+        cacheCfg = ClientCacheConfigurationSerializer.read(reader);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        try {
+            ctx.kernalContext().grid().getOrCreateCache(cacheCfg);
+        } catch (CacheExistsException e) {
+            throw new IgniteClientException(ClientStatus.CACHE_EXISTS, 
e.getMessage());
+        }
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithNameRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithNameRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithNameRequest.java
new file mode 100644
index 0000000..94dd115
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithNameRequest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.processors.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Cache create with name request.
+ */
+public class ClientCacheGetOrCreateWithNameRequest extends ClientRequest {
+    /** Cache name. */
+    private final String cacheName;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheGetOrCreateWithNameRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cacheName = reader.readString();
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        ctx.kernalContext().grid().getOrCreateCache(cacheName);
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
index c1a807c..a8df0c6 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
@@ -209,11 +209,7 @@ public class PlatformConfigurationUtils {
         ccfg.setMaxQueryIteratorsCount(in.readInt());
         ccfg.setQueryDetailMetricsSize(in.readInt());
         ccfg.setQueryParallelism(in.readInt());
-
-        String sqlSchema = in.readString();
-        if (sqlSchema != null) {
-            ccfg.setSqlSchema(sqlSchema);
-        }
+        ccfg.setSqlSchema(in.readString());
 
         int qryEntCnt = in.readInt();
 
@@ -480,12 +476,14 @@ public class PlatformConfigurationUtils {
      * @param in Stream.
      * @return QueryEntity.
      */
-    private static QueryEntity readQueryEntity(BinaryRawReader in) {
+    public static QueryEntity readQueryEntity(BinaryRawReader in) {
         QueryEntity res = new QueryEntity();
 
         res.setKeyType(in.readString());
         res.setValueType(in.readString());
         res.setTableName(in.readString());
+        res.setKeyFieldName(in.readString());
+        res.setValueFieldName(in.readString());
 
         // Fields
         int cnt = in.readInt();
@@ -541,9 +539,6 @@ public class PlatformConfigurationUtils {
             res.setIndexes(indexes);
         }
 
-        res.setKeyFieldName(in.readString());
-        res.setValueFieldName(in.readString());
-
         return res;
     }
 
@@ -988,12 +983,14 @@ public class PlatformConfigurationUtils {
      * @param writer Writer.
      * @param queryEntity Query entity.
      */
-    private static void writeQueryEntity(BinaryRawWriter writer, QueryEntity 
queryEntity) {
+    public static void writeQueryEntity(BinaryRawWriter writer, QueryEntity 
queryEntity) {
         assert queryEntity != null;
 
         writer.writeString(queryEntity.getKeyType());
         writer.writeString(queryEntity.getValueType());
         writer.writeString(queryEntity.getTableName());
+        writer.writeString(queryEntity.getKeyFieldName());
+        writer.writeString(queryEntity.getValueFieldName());
 
         // Fields
         LinkedHashMap<String, String> fields = queryEntity.getFields();
@@ -1039,9 +1036,6 @@ public class PlatformConfigurationUtils {
         }
         else
             writer.writeInt(0);
-
-        writer.writeString(queryEntity.getKeyFieldName());
-        writer.writeString(queryEntity.getValueFieldName());
     }
 
     /**
@@ -1343,7 +1337,7 @@ public class PlatformConfigurationUtils {
      * @param w Writer.
      * @param e Enum.
      */
-    private static void writeEnumInt(BinaryRawWriter w, Enum e) {
+    public static void writeEnumInt(BinaryRawWriter w, Enum e) {
         w.writeInt(e == null ? 0 : e.ordinal());
     }
 
@@ -1353,7 +1347,7 @@ public class PlatformConfigurationUtils {
      * @param w Writer.
      * @param e Enum.
      */
-    private static void writeEnumInt(BinaryRawWriter w, Enum e, Enum def) {
+    public static void writeEnumInt(BinaryRawWriter w, Enum e, Enum def) {
         assert def != null;
 
         w.writeInt(e == null ? def.ordinal() : e.ordinal());

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/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 2ef6db1..2e34ba2 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
@@ -107,7 +107,9 @@
     <Compile Include="Cache\Store\CacheStoreSessionTestSharedFactory.cs" />
     <Compile Include="Client\Cache\CacheTest.cs" />
     <Compile Include="Client\Cache\CacheTestNoMeta.cs" />
+    <Compile Include="Client\Cache\ClientCacheConfigurationTest.cs" />
     <Compile Include="Client\Cache\EmptyObject.cs" />
+    <Compile Include="Client\Cache\CreateCacheTest.cs" />
     <Compile Include="Client\Cache\ScanQueryTest.cs" />
     <Compile Include="Client\Cache\Person.cs" />
     <Compile Include="Client\ClientTestBase.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
index 9593777..63f5cd8 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
@@ -578,7 +578,7 @@ namespace Apache.Ignite.Core.Tests.Cache
         /// <summary>
         /// Gets the custom cache configuration.
         /// </summary>
-        private static CacheConfiguration GetCustomCacheConfiguration(string 
name = null)
+        public static CacheConfiguration GetCustomCacheConfiguration(string 
name = null)
         {
             return new CacheConfiguration
             {

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientCacheConfigurationTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientCacheConfigurationTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientCacheConfigurationTest.cs
new file mode 100644
index 0000000..381f924
--- /dev/null
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientCacheConfigurationTest.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.
+ */
+
+namespace Apache.Ignite.Core.Tests.Client.Cache
+{
+    using System;
+    using System.IO;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Client.Cache;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+    using Apache.Ignite.Core.Impl.Client.Cache;
+    using Apache.Ignite.Core.Tests.Cache;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests client cache configuration handling.
+    /// </summary>
+    public class ClientCacheConfigurationTest
+    {
+        /// <summary>
+        /// Tests the serialization/deserialization of <see 
cref="CacheConfiguration"/>.
+        /// </summary>
+        [Test]
+        public void TestSerializeDeserialize()
+        {
+            // Empty.
+            TestSerializeDeserialize(new CacheConfiguration("foo"));
+
+            // Full config: has unsupported properties.
+            var cfg = 
CacheConfigurationTest.GetCustomCacheConfiguration("bar");
+            cfg.ReadThrough = true;
+            cfg.WriteBehindEnabled = true;
+            
+            TestSerializeDeserializeUnspported(cfg, "AffinityFunction");
+            cfg.AffinityFunction = null;
+
+            TestSerializeDeserializeUnspported(cfg, "EvictionPolicy");
+            cfg.EvictionPolicy = null;
+
+            TestSerializeDeserializeUnspported(cfg, "ExpiryPolicyFactory");
+            cfg.ExpiryPolicyFactory = null;
+
+            TestSerializeDeserializeUnspported(cfg, "PluginConfigurations");
+            cfg.PluginConfigurations = null;
+
+            TestSerializeDeserializeUnspported(cfg, "CacheStoreFactory");
+            cfg.CacheStoreFactory = null;
+
+            TestSerializeDeserializeUnspported(cfg, "NearConfiguration");
+            cfg.NearConfiguration = null;
+
+            // Store-specific properties.
+            TestSerializeDeserializeUnspported(cfg, "KeepBinaryInStore");
+            cfg.KeepBinaryInStore = false;
+
+            TestSerializeDeserializeUnspported(cfg, "LoadPreviousValue");
+            cfg.LoadPreviousValue = false;
+
+            TestSerializeDeserializeUnspported(cfg, "ReadThrough");
+            cfg.ReadThrough = false;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteThrough");
+            cfg.WriteThrough = false;
+
+            TestSerializeDeserializeUnspported(cfg, 
"StoreConcurrentLoadAllThreshold");
+            cfg.StoreConcurrentLoadAllThreshold = 
CacheConfiguration.DefaultStoreConcurrentLoadAllThreshold;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindBatchSize");
+            cfg.WriteBehindBatchSize = 
CacheConfiguration.DefaultWriteBehindBatchSize;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindCoalescing");
+            cfg.WriteBehindCoalescing = 
CacheConfiguration.DefaultWriteBehindCoalescing;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindEnabled");
+            cfg.WriteBehindEnabled = 
CacheConfiguration.DefaultWriteBehindEnabled;
+
+            TestSerializeDeserializeUnspported(cfg, 
"WriteBehindFlushFrequency");
+            cfg.WriteBehindFlushFrequency = 
CacheConfiguration.DefaultWriteBehindFlushFrequency;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindFlushSize");
+            cfg.WriteBehindFlushSize = 
CacheConfiguration.DefaultWriteBehindFlushSize;
+
+            TestSerializeDeserializeUnspported(cfg, 
"WriteBehindFlushThreadCount");
+            cfg.WriteBehindFlushThreadCount = 
CacheConfiguration.DefaultWriteBehindFlushThreadCount;
+
+            // Full config without unsupported properties.
+            TestSerializeDeserialize(cfg);
+        }
+
+        /// <summary>
+        /// Tests <see cref="CacheConfiguration"/> to <see 
cref="CacheClientConfiguration"/> and reverse conversion.
+        /// </summary>
+        [Test]
+        public void TestConfigConversion()
+        {
+            // Copy ctor.
+            var clientCfg = new CacheClientConfiguration(
+                CacheConfigurationTest.GetCustomCacheConfiguration("z"), true);
+
+            AssertClientConfigsAreEqual(clientCfg, new 
CacheClientConfiguration(clientCfg));
+
+            // Convert to server cfg.
+            var serverCfg = clientCfg.ToCacheConfiguration();
+            AssertClientConfigsAreEqual(clientCfg, new 
CacheClientConfiguration(serverCfg, false));
+        }
+
+        /// <summary>
+        /// Tests the constructors.
+        /// </summary>
+        [Test]
+        public void TestConstructors()
+        {
+            // Default property values.
+            var clientCfg = new CacheClientConfiguration();
+            var defCfg = new CacheClientConfiguration(new 
CacheConfiguration(), false);
+
+            AssertClientConfigsAreEqual(defCfg, clientCfg);
+
+            // Name.
+            clientCfg = new CacheClientConfiguration("foo");
+            Assert.AreEqual("foo", clientCfg.Name);
+
+            clientCfg.Name = null;
+            AssertClientConfigsAreEqual(defCfg, clientCfg);
+
+            // Query entities.
+            clientCfg = new CacheClientConfiguration("bar", 
typeof(QueryPerson));
+            Assert.AreEqual("bar", clientCfg.Name);
+            var qe = clientCfg.QueryEntities.Single();
+            Assert.AreEqual(typeof(QueryPerson), qe.ValueType);
+            Assert.AreEqual("Name", qe.Fields.Single().Name);
+
+            clientCfg = new CacheClientConfiguration("baz", new 
QueryEntity(typeof(QueryPerson)));
+            qe = clientCfg.QueryEntities.Single();
+            Assert.AreEqual(typeof(QueryPerson), qe.ValueType);
+            Assert.AreEqual("Name", qe.Fields.Single().Name);
+        }
+
+        /// <summary>
+        /// Tests the serialization/deserialization of <see 
cref="CacheConfiguration"/>.
+        /// </summary>
+        private static void 
TestSerializeDeserializeUnspported(CacheConfiguration cfg, string propName)
+        {
+            var ex = Assert.Throws<NotSupportedException>(() => 
TestSerializeDeserialize(cfg));
+            Assert.AreEqual(string.Format("{0}.{1} property is not supported 
in thin client mode.",
+                typeof(CacheConfiguration).Name, propName), ex.Message);
+        }
+
+        /// <summary>
+        /// Tests the serialization/deserialization of <see 
cref="CacheConfiguration"/>.
+        /// </summary>
+        private static void TestSerializeDeserialize(CacheConfiguration cfg)
+        {
+            var clientCfg = new CacheClientConfiguration(cfg, false);
+
+            AssertClientConfigsAreEqual(clientCfg, 
SerializeDeserialize(clientCfg));
+        }
+
+        /// <summary>
+        /// Asserts the client configs are equal.
+        /// </summary>
+        public static void 
AssertClientConfigsAreEqual(CacheClientConfiguration cfg, 
CacheClientConfiguration cfg2)
+        {
+            if (cfg2.QueryEntities != null)
+            {
+                // Remove identical aliases which are added during config 
roundtrip.
+                foreach (var e in cfg2.QueryEntities)
+                {
+                    e.Aliases = e.Aliases.Where(x => x.Alias != 
x.FullName).ToArray();
+                }
+            }
+
+            TestUtils.AssertReflectionEqual(cfg, cfg2);
+        }
+
+        /// <summary>
+        /// Serializes and deserializes the config.
+        /// </summary>
+        private static CacheClientConfiguration 
SerializeDeserialize(CacheClientConfiguration cfg)
+        {
+            using (var stream = new BinaryHeapStream(128))
+            {
+                ClientCacheConfigurationSerializer.Write(stream, cfg);
+                stream.Seek(0, SeekOrigin.Begin);
+                return new CacheClientConfiguration(stream);
+            }
+        }
+
+        private class QueryPerson
+        {
+            [QuerySqlField]
+            // ReSharper disable once UnusedMember.Local
+            public string Name { get; set; }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CreateCacheTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CreateCacheTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CreateCacheTest.cs
new file mode 100644
index 0000000..c92fbac
--- /dev/null
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CreateCacheTest.cs
@@ -0,0 +1,209 @@
+/*
+ * 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.Linq;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Client;
+    using Apache.Ignite.Core.Client.Cache;
+    using Apache.Ignite.Core.Configuration;
+    using Apache.Ignite.Core.Impl.Client;
+    using Apache.Ignite.Core.Tests.Cache;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests dynamic cache start from client nodes.
+    /// </summary>
+    public class CreateCacheTest : ClientTestBase
+    {
+        /** Template cache name. */
+        private const string TemplateCacheName = "template-cache-*";
+
+        /// <summary>
+        /// Tears down the test.
+        /// </summary>
+        [TearDown]
+        public void TearDown()
+        {
+            DestroyCaches();
+        }
+
+        /// <summary>
+        /// Destroys caches.
+        /// </summary>
+        private void DestroyCaches()
+        {
+            foreach (var cacheName in Client.GetCacheNames())
+            {
+                Client.DestroyCache(cacheName);
+            }
+        }
+
+        /// <summary>
+        /// Tests the GetCacheNames.
+        /// </summary>
+        [Test]
+        public void TestGetCacheNames()
+        {
+            DestroyCaches();
+            Assert.AreEqual(0, Client.GetCacheNames().Count);
+
+            Client.CreateCache<int, int>("a");
+            Assert.AreEqual("a", Client.GetCacheNames().Single());
+
+            Client.CreateCache<int, int>("b");
+            Assert.AreEqual(new[] {"a", "b"}, Client.GetCacheNames().OrderBy(x 
=> x).ToArray());
+
+            Client.DestroyCache("a");
+            Assert.AreEqual("b", Client.GetCacheNames().Single());
+        }
+
+        /// <summary>
+        /// Tests create from template.
+        /// </summary>
+        [Test]
+        public void TestCreateFromTemplate()
+        {
+            // No template: default configuration.
+            var cache = Client.CreateCache<int, int>("foobar");
+            TestUtils.AssertReflectionEqual(new 
CacheClientConfiguration("foobar"), cache.GetConfiguration());
+
+            // Create when exists.
+            var ex = Assert.Throws<IgniteClientException>(() => 
Client.CreateCache<int, int>(cache.Name));
+            Assert.AreEqual(
+                "Failed to start cache (a cache with the same name is already 
started): foobar", ex.Message);
+            Assert.AreEqual((int) ClientStatus.CacheExists, ex.ErrorCode);
+
+            // Template: custom configuration.
+            cache = Client.CreateCache<int, 
int>(TemplateCacheName.Replace("*", "1"));
+            var cfg = cache.GetConfiguration();
+            Assert.AreEqual(CacheAtomicityMode.Transactional, 
cfg.AtomicityMode);
+            Assert.AreEqual(3, cfg.Backups);
+            Assert.AreEqual(CacheMode.Partitioned, cfg.CacheMode);
+        }
+
+        /// <summary>
+        /// Tests getOrCreate from template.
+        /// </summary>
+        [Test]
+        public void TestGetOrCreateFromTemplate()
+        {
+            // No template: default configuration.
+            var cache = Client.GetOrCreateCache<int, int>("foobar");
+            TestUtils.AssertReflectionEqual(new CacheClientConfiguration { 
Name = "foobar"}, cache.GetConfiguration());
+            cache[1] = 1;
+
+            // Create when exists.
+            cache = Client.GetOrCreateCache<int, int>("foobar");
+            Assert.AreEqual(1, cache[1]);
+
+            // Template: custom configuration.
+            cache = Client.GetOrCreateCache<int, 
int>(TemplateCacheName.Replace("*", "1"));
+            var cfg = cache.GetConfiguration();
+            Assert.AreEqual(CacheAtomicityMode.Transactional, 
cfg.AtomicityMode);
+            Assert.AreEqual(3, cfg.Backups);
+            Assert.AreEqual(CacheMode.Partitioned, cfg.CacheMode);
+
+            // Create when exists.
+            cache[1] = 1;
+            cache = Client.GetOrCreateCache<int, int>(cache.Name);
+            Assert.AreEqual(1, cache[1]);
+        }
+
+        /// <summary>
+        /// Tests cache creation from configuration.
+        /// </summary>
+        [Test]
+        public void TestCreateFromConfiguration()
+        {
+            // Default config.
+            var cfg = new CacheClientConfiguration("a");
+            var cache = Client.CreateCache<int, int>(cfg);
+            TestUtils.AssertReflectionEqual(cfg, cache.GetConfiguration());
+
+            // Create when exists.
+            var ex = Assert.Throws<IgniteClientException>(() => 
Client.CreateCache<int, int>(cfg));
+            Assert.AreEqual(
+                "Failed to start cache (a cache with the same name is already 
started): a", ex.Message);
+            Assert.AreEqual((int) ClientStatus.CacheExists, ex.ErrorCode);
+
+            // Custom config.
+            cfg = GetFullCacheConfiguration("b");
+
+            cache = Client.CreateCache<int, int>(cfg);
+            ClientCacheConfigurationTest.AssertClientConfigsAreEqual(cfg, 
cache.GetConfiguration());
+        }
+
+        /// <summary>
+        /// Tests cache creation from configuration.
+        /// </summary>
+        [Test]
+        public void TestGetOrCreateFromConfiguration()
+        {
+            // Default configur.
+            var cfg = new CacheClientConfiguration("a");
+            var cache = Client.GetOrCreateCache<int, int>(cfg);
+            TestUtils.AssertReflectionEqual(cfg, cache.GetConfiguration());
+            cache[1] = 1;
+
+            // Create when exists.
+            cache = Client.GetOrCreateCache<int, int>("a");
+            Assert.AreEqual(1, cache[1]);
+
+            // Custom config.
+            cfg = GetFullCacheConfiguration("b");
+
+            cache = Client.GetOrCreateCache<int, int>(cfg);
+            ClientCacheConfigurationTest.AssertClientConfigsAreEqual(cfg, 
cache.GetConfiguration());
+        }
+
+        /// <summary>
+        /// Gets the full cache configuration.
+        /// </summary>
+        private static CacheClientConfiguration 
GetFullCacheConfiguration(string name)
+        {
+            return new 
CacheClientConfiguration(CacheConfigurationTest.GetCustomCacheConfiguration(name),
 true);
+        }
+
+        /** <inheritdoc /> */
+        protected override IgniteConfiguration GetIgniteConfiguration()
+        {
+            return new IgniteConfiguration(base.GetIgniteConfiguration())
+            {
+                CacheConfiguration = new[]
+                {
+                    new CacheConfiguration(TemplateCacheName)
+                    {
+                        AtomicityMode = CacheAtomicityMode.Transactional,
+                        Backups = 3
+                    }
+                },
+                DataStorageConfiguration = new DataStorageConfiguration
+                {
+                    DataRegionConfigurations = new[]
+                    {
+                        new DataRegionConfiguration
+                        {
+                            Name = "myMemPolicy"
+                        } 
+                    }
+                }
+            };
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/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
index 408eb73..9b7a566 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
@@ -64,6 +64,8 @@ namespace Apache.Ignite.Core.Tests.Client
             {
                 Ignition.Start(cfg);
             }
+
+            Client = GetClient();
         }
 
         /// <summary>
@@ -85,6 +87,11 @@ namespace Apache.Ignite.Core.Tests.Client
         }
 
         /// <summary>
+        /// Gets the client.
+        /// </summary>
+        public IIgniteClient Client { get; set; }
+
+        /// <summary>
         /// Gets the cache.
         /// </summary>
         protected static ICache<int, T> GetCache<T>()

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
index 6e09704..98c3f11 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
@@ -27,6 +27,7 @@ namespace Apache.Ignite.Core.Tests
     using Apache.Ignite.Core.Cache.Configuration;
     using Apache.Ignite.Core.Cache.Eviction;
     using Apache.Ignite.Core.Client;
+    using Apache.Ignite.Core.Client.Cache;
     using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Communication.Tcp;
     using Apache.Ignite.Core.Configuration;
@@ -99,6 +100,7 @@ namespace Apache.Ignite.Core.Tests
             CheckDefaultValueAttributes(new QueryIndex());
             CheckDefaultValueAttributes(new DataStorageConfiguration());
             CheckDefaultValueAttributes(new DataRegionConfiguration());
+            CheckDefaultValueAttributes(new CacheClientConfiguration());
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/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 8a32583..0076d47 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -96,6 +96,7 @@
     <Compile Include="Binary\TimestampAttribute.cs" />
     <Compile Include="Cache\Configuration\CacheKeyConfiguration.cs" />
     <Compile Include="Cache\Configuration\DataPageEvictionMode.cs" />
+    <Compile Include="Client\Cache\CacheClientConfiguration.cs" />
     <Compile Include="Configuration\CheckpointWriteOrder.cs" />
     <Compile Include="Configuration\DataPageEvictionMode.cs" />
     <Compile Include="Configuration\DataRegionConfiguration.cs" />
@@ -119,6 +120,7 @@
     <Compile Include="Impl\Binary\MultidimensionalArrayHolder.cs" />
     <Compile Include="Impl\Binary\MultidimensionalArraySerializer.cs" />
     <Compile Include="Impl\Client\Cache\CacheFlags.cs" />
+    <Compile Include="Impl\Client\Cache\ClientCacheConfigurationSerializer.cs" 
/>
     <Compile Include="Impl\Client\Cache\Query\ClientQueryCursor.cs" />
     <Compile Include="Impl\Cache\Query\PlatformQueryQursorBase.cs" />
     <Compile Include="Impl\Binary\BinaryProcessorClient.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
index eb509a0..4db15eb 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
@@ -237,6 +237,8 @@ namespace Apache.Ignite.Core.Cache.Configuration
             KeyTypeName = reader.ReadString();
             ValueTypeName = reader.ReadString();
             TableName = reader.ReadString();
+            KeyFieldName = reader.ReadString();
+            ValueFieldName = reader.ReadString();
 
             var count = reader.ReadInt();
             Fields = count == 0
@@ -249,9 +251,6 @@ namespace Apache.Ignite.Core.Cache.Configuration
 
             count = reader.ReadInt();
             Indexes = count == 0 ? null : Enumerable.Range(0, count).Select(x 
=> new QueryIndex(reader)).ToList();
-
-            KeyFieldName = reader.ReadString();
-            ValueFieldName = reader.ReadString();
         }
 
         /// <summary>
@@ -262,6 +261,8 @@ namespace Apache.Ignite.Core.Cache.Configuration
             writer.WriteString(KeyTypeName);
             writer.WriteString(ValueTypeName);
             writer.WriteString(TableName);
+            writer.WriteString(KeyFieldName);
+            writer.WriteString(ValueFieldName);
 
             if (Fields != null)
             {
@@ -303,9 +304,6 @@ namespace Apache.Ignite.Core.Cache.Configuration
             }
             else
                 writer.WriteInt(0);
-
-            writer.WriteString(KeyFieldName);
-            writer.WriteString(ValueFieldName);
         }
 
         /// <summary>

Reply via email to