You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2018/08/30 21:15:42 UTC

ignite git commit: IGNITE-9116 .NET: LINQ: Use CacheConfiguration.SqlSchema when generating SQL

Repository: ignite
Updated Branches:
  refs/heads/master 78328fe49 -> 2108b3b83


IGNITE-9116 .NET: LINQ: Use CacheConfiguration.SqlSchema when generating SQL

This closes #4642


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

Branch: refs/heads/master
Commit: 2108b3b836d113d8996c1e558a1681e5ebf251c6
Parents: 78328fe
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Aug 31 00:15:28 2018 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Aug 31 00:15:28 2018 +0300

----------------------------------------------------------------------
 .../ExpiryCacheHolderTest.cs                    |  5 --
 .../IgniteSessionStateStoreProviderTest.cs      |  7 +--
 .../Cache/Query/Linq/CacheLinqTest.Base.cs      | 20 +++++--
 .../Query/Linq/CacheLinqTest.Introspection.cs   | 22 ++++----
 .../IgniteStartStopTest.cs                      | 23 ++++----
 .../Apache.Ignite.Core.Tests/MessagingTest.cs   | 13 ++---
 .../Apache.Ignite.Core.Tests/ReconnectTest.cs   |  3 +-
 .../Apache.Ignite.Core/IgniteConfiguration.cs   | 56 +++++++++----------
 .../Apache.Ignite.Linq/Impl/ExpressionWalker.cs | 58 ++++++++++++++++++--
 9 files changed, 128 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/2108b3b8/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs b/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs
index b3d5228..eb27977 100644
--- a/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs
@@ -416,11 +416,6 @@ namespace Apache.Ignite.AspNet.Tests
                 throw new NotImplementedException();
             }
 
-            public void LocalPromote(IEnumerable<int> keys)
-            {
-                throw new NotImplementedException();
-            }
-
             public IQueryCursor<ICacheEntry<int, int>> Query(QueryBase qry)
             {
                 throw new NotImplementedException();

http://git-wip-us.apache.org/repos/asf/ignite/blob/2108b3b8/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/IgniteSessionStateStoreProviderTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/IgniteSessionStateStoreProviderTest.cs b/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/IgniteSessionStateStoreProviderTest.cs
index 08c44a6..da074ac 100644
--- a/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/IgniteSessionStateStoreProviderTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/IgniteSessionStateStoreProviderTest.cs
@@ -23,7 +23,6 @@ namespace Apache.Ignite.AspNet.Tests
     using System.Linq;
     using System.Reflection;
     using System.Threading;
-    using System.Threading.Tasks;
     using System.Web;
     using System.Web.SessionState;
     using Apache.Ignite.Core;
@@ -56,7 +55,7 @@ namespace Apache.Ignite.AspNet.Tests
         private const string Id = "1";
 
         /** Test context. */
-        private static readonly HttpContext HttpContext = 
+        private static readonly HttpContext HttpContext =
             new HttpContext(new HttpRequest(null, "http://tempuri.org", null), new HttpResponse(null));
 
         /// <summary>
@@ -87,7 +86,7 @@ namespace Apache.Ignite.AspNet.Tests
             var ignite = Ignition.GetIgnite(GridName);
             ignite.GetCacheNames().ToList().ForEach(x => ignite.GetCache<object, object>(x).RemoveAll());
         }
-        
+
         /// <summary>
         /// Test setup.
         /// </summary>
@@ -230,7 +229,7 @@ namespace Apache.Ignite.AspNet.Tests
 
             // Add item.
             provider.CreateUninitializedItem(HttpContext, Id, 7);
-            
+
             // Check added item.
             res = provider.GetItem(HttpContext, Id, out locked, out lockAge, out lockId, out actions);
             Assert.IsNotNull(res);

http://git-wip-us.apache.org/repos/asf/ignite/blob/2108b3b8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
index 5b56abd..81dcfed 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
@@ -45,11 +45,17 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
         /** Cache name. */
         private const string PersonOrgCacheName = "person_org";
 
+        /** Cache schema. */
+        private const string PersonOrgCacheSchema = "person_org_Schema";
+
         /** Cache name. */
         private const string PersonSecondCacheName = "person_cache";
 
-        /** Role cache name. */
-        private const string RoleCacheName = "role_cache";
+        /** Cache schema. */
+        private const string PersonSecondCacheSchema = "\"person_cache_SCHEMA\"";
+
+        /** Role cache name: uses invalid characters to test name escaping. */
+        private const string RoleCacheName = "role$ cache.";
 
         /** */
         private const int RoleCount = 3;
@@ -199,7 +205,8 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
                     new QueryEntity(typeof (int), typeof (Organization)))
                 {
                     CacheMode = CacheMode.Replicated,
-                    SqlEscapeAll = GetSqlEscapeAll()
+                    SqlEscapeAll = GetSqlEscapeAll(),
+                    SqlSchema = PersonOrgCacheSchema
                 });
         }
 
@@ -231,14 +238,15 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
                         })
                     {
                         CacheMode = CacheMode.Replicated,
-                        SqlEscapeAll = GetSqlEscapeAll()
+                        SqlEscapeAll = GetSqlEscapeAll(),
+                        SqlSchema = PersonSecondCacheSchema
                     });
         }
 
         /// <summary>
         /// Checks that function maps to SQL function properly.
         /// </summary>
-        private static void CheckFunc<T, TR>(Expression<Func<T, TR>> exp, IQueryable<T> query, 
+        private static void CheckFunc<T, TR>(Expression<Func<T, TR>> exp, IQueryable<T> query,
             Func<TR, TR> localResultFunc = null)
         {
             localResultFunc = localResultFunc ?? (x => x);
@@ -263,7 +271,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
         /// <summary>
         /// Checks that function used in Where Clause maps to SQL function properly
         /// </summary>
-        private static void CheckWhereFunc<TKey, TEntry>(IQueryable<ICacheEntry<TKey,TEntry>> query, 
+        private static void CheckWhereFunc<TKey, TEntry>(IQueryable<ICacheEntry<TKey,TEntry>> query,
             Expression<Func<ICacheEntry<TKey, TEntry>,bool>> whereExpression)
         {
             // Calculate result locally, using real method invocation

http://git-wip-us.apache.org/repos/asf/ignite/blob/2108b3b8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
index aa26548..f5b5baa 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
@@ -66,8 +66,8 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
 
             Assert.AreEqual(
                 GetSqlEscapeAll()
-                    ? "select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where (_T0.\"_KEY\" > ?)"
-                    : "select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where (_T0._KEY > ?)",
+                    ? "select _T0._KEY, _T0._VAL from PERSON_ORG_SCHEMA.\"Person\" as _T0 where (_T0.\"_KEY\" > ?)"
+                    : "select _T0._KEY, _T0._VAL from PERSON_ORG_SCHEMA.Person as _T0 where (_T0._KEY > ?)",
                 fq.Sql);
 
             Assert.AreEqual(new[] { 10 }, fq.Arguments);
@@ -84,12 +84,12 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
             var str = query.ToString();
             Assert.AreEqual(GetSqlEscapeAll()
                 ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
+                  "[Sql=select _T0._KEY, _T0._VAL from PERSON_ORG_SCHEMA.\"Person\" as _T0 where " +
                   "(_T0.\"_KEY\" > ?), Arguments=[10], " +
                   "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
                   "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=, Lazy=True]]"
                 : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
+                  "[Sql=select _T0._KEY, _T0._VAL from PERSON_ORG_SCHEMA.Person as _T0 where " +
                   "(_T0._KEY > ?), Arguments=[10], " +
                   "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
                   "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=, Lazy=True]]", str);
@@ -104,8 +104,8 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
 
             fq = fieldsQuery.GetFieldsQuery();
             Assert.AreEqual(GetSqlEscapeAll()
-                    ? "select _T0.\"Name\" from \"person_org\".\"Person\" as _T0"
-                    : "select _T0.NAME from \"person_org\".Person as _T0",
+                    ? "select _T0.\"Name\" from PERSON_ORG_SCHEMA.\"Person\" as _T0"
+                    : "select _T0.NAME from PERSON_ORG_SCHEMA.Person as _T0",
                 fq.Sql);
 
             Assert.IsFalse(fq.Local);
@@ -117,11 +117,11 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
             str = fieldsQuery.ToString();
             Assert.AreEqual(GetSqlEscapeAll()
                 ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0.\"Name\" from \"person_org\".\"Person\" as _T0, Arguments=[], Local=False, " +
+                  "[Sql=select _T0.\"Name\" from PERSON_ORG_SCHEMA.\"Person\" as _T0, Arguments=[], Local=False, " +
                   "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
                   "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=, Lazy=False]]"
                 : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0.NAME from \"person_org\".Person as _T0, Arguments=[], Local=False, " +
+                  "[Sql=select _T0.NAME from PERSON_ORG_SCHEMA.Person as _T0, Arguments=[], Local=False, " +
                   "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
                   "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=, Lazy=False]]", str);
 
@@ -136,17 +136,17 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
             str = distrQuery.ToString();
             Assert.AreEqual(GetSqlEscapeAll()
                 ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
+                  "[Sql=select _T0._KEY, _T0._VAL from PERSON_ORG_SCHEMA.\"Person\" as _T0 where " +
                   "(((_T0.\"_KEY\" > ?) and (_T0.\"age1\" > ?)) " +
                   "and (_T0.\"Name\" like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
                   "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
                   "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=, Lazy=False]]"
                 : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
-                  "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
+                  "[Sql=select _T0._KEY, _T0._VAL from PERSON_ORG_SCHEMA.Person as _T0 where " +
                   "(((_T0._KEY > ?) and (_T0.AGE1 > ?)) " +
                   "and (_T0.NAME like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
                   "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
                   "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=, Lazy=False]]", str);
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/2108b3b8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
index f9c1cad..dd6a7b2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
@@ -15,13 +15,12 @@
  * limitations under the License.
  */
 
-namespace Apache.Ignite.Core.Tests 
+namespace Apache.Ignite.Core.Tests
 {
     using System;
     using System.IO;
     using System.Linq;
     using System.Threading;
-    using System.Threading.Tasks;
     using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Impl.Common;
     using Apache.Ignite.Core.Messaging;
@@ -45,7 +44,7 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
-        /// 
+        ///
         /// </summary>
         [Test]
         public void TestStartDefault()
@@ -60,7 +59,7 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
-        /// 
+        ///
         /// </summary>
         [Test]
         public void TestStartWithConfigPath()
@@ -79,7 +78,7 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
-        /// 
+        ///
         /// </summary>
         [Test]
         public void TestStartGetStop()
@@ -140,7 +139,7 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
-        /// 
+        ///
         /// </summary>
         [Test]
         public void TestStartTheSameName()
@@ -148,7 +147,7 @@ namespace Apache.Ignite.Core.Tests
             var cfg = TestUtils.GetTestConfiguration(name: "grid1");
             var grid1 = Ignition.Start(cfg);
             Assert.AreEqual("grid1", grid1.Name);
-            
+
             var ex = Assert.Throws<IgniteException>(() => Ignition.Start(cfg));
             Assert.AreEqual("Ignite instance with this name has already been started: grid1", ex.Message);
         }
@@ -173,7 +172,7 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
-        /// 
+        ///
         /// </summary>
         [Test]
         public void TestUsageAfterStop()
@@ -191,7 +190,7 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
-        /// 
+        ///
         /// </summary>
         [Test]
         public void TestStartStopLeak()
@@ -244,7 +243,7 @@ namespace Apache.Ignite.Core.Tests
                     }
                 }
             }
-            finally 
+            finally
             {
                 Ignition.ClientMode = false;
             }
@@ -299,13 +298,13 @@ namespace Apache.Ignite.Core.Tests
                 "-jvmClasspath=" + TestUtils.CreateTestClasspath(),
                 "-springConfigUrl=" + Path.GetFullPath(cfg.SpringConfigUrl),
                 "-J-Xms512m", "-J-Xmx512m");
-            
+
             Assert.IsTrue(proc.Alive);
 
             var cts = new CancellationTokenSource();
             var token = cts.Token;
 
-            // Spam message subscriptions on a separate thread 
+            // Spam message subscriptions on a separate thread
             // to test race conditions during processor init on remote node
             var listenTask = TaskRunner.Run(() =>
             {

http://git-wip-us.apache.org/repos/asf/ignite/blob/2108b3b8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs
index 7db4eef..5dfa82f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs
@@ -23,7 +23,6 @@ namespace Apache.Ignite.Core.Tests
     using System.Diagnostics.CodeAnalysis;
     using System.Linq;
     using System.Threading;
-    using System.Threading.Tasks;
     using Apache.Ignite.Core.Cache.Configuration;
     using Apache.Ignite.Core.Cluster;
     using Apache.Ignite.Core.Common;
@@ -59,7 +58,7 @@ namespace Apache.Ignite.Core.Tests
             DateTime.Now,
             byte.MinValue,
             short.MaxValue,
-            
+
             // Enums.
             CacheMode.Local,
             GCCollectionMode.Forced,
@@ -94,7 +93,7 @@ namespace Apache.Ignite.Core.Tests
 
                 MessagingTestHelper.AssertFailures();
             }
-            finally 
+            finally
             {
                 // Stop all grids between tests to drop any hanging messages
                 Ignition.StopAll(true);
@@ -466,7 +465,7 @@ namespace Apache.Ignite.Core.Tests
 
             if (sharedResult.Length != 0)
             {
-                Assert.Fail("Unexpected messages ({0}): {1}; last sent message: {2}", sharedResult.Length, 
+                Assert.Fail("Unexpected messages ({0}): {1}; last sent message: {2}", sharedResult.Length,
                     string.Join(",", sharedResult), lastMsg);
             }
         }
@@ -574,7 +573,7 @@ namespace Apache.Ignite.Core.Tests
     {
         /** */
         public static readonly ConcurrentStack<string> ReceivedMessages = new ConcurrentStack<string>();
-        
+
         /** */
         private static readonly ConcurrentStack<string> Failures = new ConcurrentStack<string>();
 
@@ -626,7 +625,7 @@ namespace Apache.Ignite.Core.Tests
             // check that all messages came from local node.
             var localNodeId = cluster.Ignite.GetCluster().GetLocalNode().Id;
             Assert.AreEqual(localNodeId, LastNodeIds.Distinct().Single());
-            
+
             AssertFailures();
         }
 
@@ -670,7 +669,7 @@ namespace Apache.Ignite.Core.Tests
                 }
                 catch (Exception ex)
                 {
-                    // When executed on remote nodes, these exceptions will not go to sender, 
+                    // When executed on remote nodes, these exceptions will not go to sender,
                     // so we have to accumulate them.
                     Failures.Push(string.Format("Exception in Listen (msg: {0}, id: {1}): {2}", message, nodeId, ex));
                     throw;

http://git-wip-us.apache.org/repos/asf/ignite/blob/2108b3b8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs
index 274439e..5d40408 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs
@@ -17,7 +17,6 @@
 
 namespace Apache.Ignite.Core.Tests
 {
-    using System;
     using System.Threading;
     using Apache.Ignite.Core.Cache;
     using Apache.Ignite.Core.Cache.Configuration;
@@ -83,7 +82,7 @@ namespace Apache.Ignite.Core.Tests
 
             // Check reconnect task.
             Assert.IsTrue(ex.ClientReconnectTask.Result);
-            
+
             // Wait a bit for notifications.
             Thread.Sleep(100);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/2108b3b8/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
index 0d66b9f..55d358a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -529,7 +529,7 @@ namespace Apache.Ignite.Core
 
             // SSL Context factory.
             SslFactorySerializer.Write(writer, SslContextFactory);
-            
+
             // Failure handler.
             if (FailureHandler == null)
             {
@@ -538,7 +538,7 @@ namespace Apache.Ignite.Core
             else
             {
                 writer.WriteBoolean(true);
-                
+
                 if (FailureHandler is NoOpFailureHandler)
                 {
                     writer.WriteByte(0);
@@ -547,7 +547,7 @@ namespace Apache.Ignite.Core
                 {
                     writer.WriteByte(1);
                 }
-                else 
+                else
                 {
                     var failHnd = FailureHandler as StopNodeOrHaltFailureHandler;
 
@@ -565,7 +565,7 @@ namespace Apache.Ignite.Core
                     failHnd.Write(writer);
                 }
             }
-           
+
             // Plugins (should be last).
             if (PluginConfigurations != null)
             {
@@ -806,7 +806,7 @@ namespace Apache.Ignite.Core
 
             // SSL context factory.
             SslContextFactory = SslFactorySerializer.Read(r);
-            
+
             //Failure handler.
             if (r.ReadBoolean())
             {
@@ -814,22 +814,22 @@ namespace Apache.Ignite.Core
                 {
                     case 0:
                         FailureHandler = new NoOpFailureHandler();
-                        
+
                         break;
 
                     case 1:
                         FailureHandler = new StopNodeFailureHandler();
-                        
+
                         break;
 
                     case 2:
                         FailureHandler = StopNodeOrHaltFailureHandler.Read(r);
-                        
+
                         break;
-                    
+
                     default:
                         FailureHandler = null;
-                        
+
                         break;
                 }
             }
@@ -960,7 +960,7 @@ namespace Apache.Ignite.Core
         /// Null property values do not override Spring values.
         /// Value-typed properties are tracked internally: if setter was not called, Spring value won't be overwritten.
         /// <para />
-        /// This merging happens on the top level only; e. g. if there are cache configurations defined in Spring 
+        /// This merging happens on the top level only; e. g. if there are cache configurations defined in Spring
         /// and in .NET, .NET caches will overwrite Spring caches.
         /// </summary>
         [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")]
@@ -991,7 +991,7 @@ namespace Apache.Ignite.Core
 
         /// <summary>
         /// List of additional .Net assemblies to load on Ignite start. Each item can be either
-        /// fully qualified assembly name, path to assembly to DLL or path to a directory when 
+        /// fully qualified assembly name, path to assembly to DLL or path to a directory when
         /// assemblies reside.
         /// </summary>
         [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
@@ -1047,7 +1047,7 @@ namespace Apache.Ignite.Core
         }
 
         /// <summary>
-        /// Gets or sets a set of event types (<see cref="EventType" />) to be recorded by Ignite. 
+        /// Gets or sets a set of event types (<see cref="EventType" />) to be recorded by Ignite.
         /// </summary>
         [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
         public ICollection<int> IncludedEventTypes { get; set; }
@@ -1187,11 +1187,11 @@ namespace Apache.Ignite.Core
         public string WorkDirectory { get; set; }
 
         /// <summary>
-        /// Gets or sets system-wide local address or host for all Ignite components to bind to. 
+        /// Gets or sets system-wide local address or host for all Ignite components to bind to.
         /// If provided it will override all default local bind settings within Ignite.
         /// <para />
-        /// If <c>null</c> then Ignite tries to use local wildcard address.That means that all services 
-        /// will be available on all network interfaces of the host machine. 
+        /// If <c>null</c> then Ignite tries to use local wildcard address.That means that all services
+        /// will be available on all network interfaces of the host machine.
         /// <para />
         /// It is strongly recommended to set this parameter for all production environments.
         /// </summary>
@@ -1200,11 +1200,11 @@ namespace Apache.Ignite.Core
         /// <summary>
         /// Gets or sets a value indicating whether this node should be a daemon node.
         /// <para />
-        /// Daemon nodes are the usual grid nodes that participate in topology but not visible on the main APIs, 
+        /// Daemon nodes are the usual grid nodes that participate in topology but not visible on the main APIs,
         /// i.e. they are not part of any cluster groups.
         /// <para />
-        /// Daemon nodes are used primarily for management and monitoring functionality that is built on Ignite 
-        /// and needs to participate in the topology, but also needs to be excluded from the "normal" topology, 
+        /// Daemon nodes are used primarily for management and monitoring functionality that is built on Ignite
+        /// and needs to participate in the topology, but also needs to be excluded from the "normal" topology,
         /// so that it won't participate in the task execution or in-memory data grid storage.
         /// </summary>
         public bool IsDaemon
@@ -1241,14 +1241,14 @@ namespace Apache.Ignite.Core
         /// affinity assignment mode is disabled then new affinity mapping is applied immediately.
         /// <para />
         /// With late affinity assignment mode, if primary node was changed for some partition, but data for this
-        /// partition is not rebalanced yet on this node, then current primary is not changed and new primary 
-        /// is temporary assigned as backup. This nodes becomes primary only when rebalancing for all assigned primary 
-        /// partitions is finished. This mode can show better performance for cache operations, since when cache 
-        /// primary node executes some operation and data is not rebalanced yet, then it sends additional message 
+        /// partition is not rebalanced yet on this node, then current primary is not changed and new primary
+        /// is temporary assigned as backup. This nodes becomes primary only when rebalancing for all assigned primary
+        /// partitions is finished. This mode can show better performance for cache operations, since when cache
+        /// primary node executes some operation and data is not rebalanced yet, then it sends additional message
         /// to force rebalancing from other nodes.
         /// <para />
         /// Note, that <see cref="ICacheAffinity"/> interface provides assignment information taking late assignment
-        /// into account, so while rebalancing for new primary nodes is not finished it can return assignment 
+        /// into account, so while rebalancing for new primary nodes is not finished it can return assignment
         /// which differs from assignment calculated by AffinityFunction.
         /// <para />
         /// This property should have the same value for all nodes in cluster.
@@ -1313,7 +1313,7 @@ namespace Apache.Ignite.Core
         public ILogger Logger { get; set; }
 
         /// <summary>
-        /// Gets or sets the failure detection timeout used by <see cref="TcpDiscoverySpi"/> 
+        /// Gets or sets the failure detection timeout used by <see cref="TcpDiscoverySpi"/>
         /// and <see cref="TcpCommunicationSpi"/>.
         /// </summary>
         [DefaultValue(typeof(TimeSpan), "00:00:10")]
@@ -1540,7 +1540,7 @@ namespace Apache.Ignite.Core
         public bool RedirectJavaConsoleOutput { get; set; }
 
         /// <summary>
-        /// Gets or sets whether user authentication is enabled for the cluster. Default is <c>false</c>. 
+        /// Gets or sets whether user authentication is enabled for the cluster. Default is <c>false</c>.
         /// </summary>
         [DefaultValue(DefaultAuthenticationEnabled)]
         public bool AuthenticationEnabled
@@ -1557,7 +1557,7 @@ namespace Apache.Ignite.Core
         /// <para><see cref="StopNodeOrHaltFailureHandler"/> -- try to stop node if tryStop value is true.
         /// If node can't be stopped during provided timeout or tryStop value is false then JVM process will be terminated forcibly.</para>
         /// <para/>
-        /// Only these implementations are supported: 
+        /// Only these implementations are supported:
         /// <see cref="NoOpFailureHandler"/>, <see cref="StopNodeOrHaltFailureHandler"/>, <see cref="StopNodeFailureHandler"/>.
         /// </summary>
         public IFailureHandler FailureHandler { get; set; }
@@ -1568,6 +1568,6 @@ namespace Apache.Ignite.Core
         /// <para/>
         /// By default schema names are case-insensitive. Use quotes to enforce case sensitivity.
         /// </summary>
-        public ICollection<String> SqlSchemas { get; set; }
+        public ICollection<string> SqlSchemas { get; set; }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/2108b3b8/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
index 0d6306a..9a684d9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
@@ -33,6 +33,9 @@ namespace Apache.Ignite.Linq.Impl
     /// </summary>
     internal static class ExpressionWalker
     {
+        /** SQL quote */
+        private const string SqlQuote = "\"";
+
         /** Compiled member readers. */
         private static readonly CopyOnWriteConcurrentDictionary<MemberInfo, Func<object, object>> MemberReaders =
             new CopyOnWriteConcurrentDictionary<MemberInfo, Func<object, object>>();
@@ -251,10 +254,57 @@ namespace Apache.Ignite.Linq.Impl
 
             var cacheCfg = queryable.CacheConfiguration;
 
-            return string.Format(cacheCfg.SqlEscapeAll
-                    ? "\"{0}\".\"{1}\""
-                    : "\"{0}\".{1}",
-                cacheCfg.Name, queryable.TableName);
+            var tableName = queryable.TableName;
+            if (cacheCfg.SqlEscapeAll)
+            {
+                tableName = string.Format("{0}{1}{0}", SqlQuote, tableName);
+            }
+
+            var schemaName = NormalizeSchemaName(cacheCfg.Name, cacheCfg.SqlSchema);
+
+            return string.Format("{0}.{1}", schemaName, tableName);
+        }
+
+        /// <summary>
+        /// Normalizes SQL schema name, see
+        /// <c>org.apache.ignite.internal.processors.query.QueryUtils#normalizeSchemaName</c>
+        /// </summary>
+        private static string NormalizeSchemaName(string cacheName, string schemaName)
+        {
+            if (schemaName == null)
+            {
+                // If schema name is not set explicitly, we will use escaped cache name. The reason is that cache name
+                // could contain weird characters, such as underscores, dots or non-Latin stuff, which are invalid from
+                // SQL syntax perspective. We do not want node to fail on startup due to this.
+                return string.Format("{0}{1}{0}", SqlQuote, cacheName);
+            }
+
+            if (schemaName.StartsWith(SqlQuote, StringComparison.Ordinal)
+                && schemaName.EndsWith(SqlQuote, StringComparison.Ordinal))
+            {
+                return schemaName;
+            }
+
+            return NormalizeObjectName(schemaName, false);
+        }
+
+        /// <summary>
+        /// Normalizes SQL object name, see
+        /// <c>org.apache.ignite.internal.processors.query.QueryUtils#normalizeObjectName</c>
+        /// </summary>
+        private static string NormalizeObjectName(string name, bool replace)
+        {
+            if (string.IsNullOrEmpty(name))
+            {
+                return name;
+            }
+
+            if (replace)
+            {
+                name = name.Replace('.', '_').Replace('$', '_');
+            }
+
+            return name.ToUpperInvariant();
         }
     }
 }