@@ -142,7 +142,7 @@ public static string ToDynamicLinqString(this TermNode node, ISqlQueryVisitorCon
142142 {
143143 FieldInfo = fieldInfo ,
144144 Term = node . Term ,
145- Operator = SqlSearchOperator . StartsWith
145+ Operator = context . DefaultSearchOperator
146146 } ;
147147 fieldTerms [ fieldInfo ] = searchTerm ;
148148 }
@@ -164,10 +164,12 @@ public static string ToDynamicLinqString(this TermNode node, ISqlQueryVisitorCon
164164 var searchTerm = kvp . Value ;
165165 var tokens = kvp . Value . Tokens ?? [ kvp . Value . Term ] ;
166166 var ( fieldPrefix , fieldSuffix ) = kvp . Key . GetFieldPrefixAndSuffix ( ) ;
167+ var ( scopePrefix , argumentPrefix ) = SplitFieldPrefix ( kvp . Key , fieldPrefix ) ;
167168
168169 if ( searchTerm . Operator == SqlSearchOperator . Equals )
169170 {
170- builder . Append ( fieldPrefix ) ;
171+ builder . Append ( scopePrefix ) ;
172+ builder . Append ( argumentPrefix ) ;
171173 builder . Append ( kvp . Key . Name ) ;
172174 builder . Append ( " in (" ) ;
173175 for ( int i = 0 ; i < tokens . Count ; i ++ )
@@ -185,11 +187,27 @@ public static string ToDynamicLinqString(this TermNode node, ISqlQueryVisitorCon
185187 tokens . ForEach ( ( token , i ) =>
186188 {
187189 builder . Append ( i . IsFirst ? "(" : " OR " ) ;
188- builder . Append ( fieldPrefix ) ;
189- builder . Append ( kvp . Key . Name ) ;
190- builder . Append ( ".Contains(" ) ;
191- AppendField ( builder , kvp . Key , token , context ) ;
192- builder . Append ( ")" ) ;
190+
191+ builder . Append ( scopePrefix ) ;
192+
193+ if ( context . FullTextFields . Contains ( kvp . Key . FullName , StringComparer . OrdinalIgnoreCase ) )
194+ {
195+ builder . Append ( "FTS.Contains(" ) ;
196+ builder . Append ( argumentPrefix ) ;
197+ builder . Append ( kvp . Key . Name ) ;
198+ builder . Append ( ", " ) ;
199+ AppendField ( builder , kvp . Key , token , context ) ;
200+ builder . Append ( ")" ) ;
201+ }
202+ else
203+ {
204+ builder . Append ( argumentPrefix ) ;
205+ builder . Append ( kvp . Key . Name ) ;
206+ builder . Append ( ".Contains(" ) ;
207+ AppendField ( builder , kvp . Key , token , context ) ;
208+ builder . Append ( ")" ) ;
209+ }
210+
193211 builder . Append ( fieldSuffix ) ;
194212 if ( i . IsLast )
195213 builder . Append ( ")" ) ;
@@ -200,11 +218,26 @@ public static string ToDynamicLinqString(this TermNode node, ISqlQueryVisitorCon
200218 tokens . ForEach ( ( token , i ) =>
201219 {
202220 builder . Append ( i . IsFirst ? "(" : " OR " ) ;
203- builder . Append ( fieldPrefix ) ;
204- builder . Append ( kvp . Key . Name ) ;
205- builder . Append ( ".StartsWith(" ) ;
206- AppendField ( builder , kvp . Key , token , context ) ;
207- builder . Append ( ")" ) ;
221+ builder . Append ( scopePrefix ) ;
222+
223+ if ( context . FullTextFields . Contains ( kvp . Key . FullName , StringComparer . OrdinalIgnoreCase ) )
224+ {
225+ builder . Append ( "FTS.Contains(" ) ;
226+ builder . Append ( argumentPrefix ) ;
227+ builder . Append ( kvp . Key . Name ) ;
228+ builder . Append ( ", " ) ;
229+ AppendField ( builder , kvp . Key , "\\ \" " + token + "*\\ \" " , context ) ;
230+ builder . Append ( ")" ) ;
231+ }
232+ else
233+ {
234+ builder . Append ( argumentPrefix ) ;
235+ builder . Append ( kvp . Key . Name ) ;
236+ builder . Append ( ".StartsWith(" ) ;
237+ AppendField ( builder , kvp . Key , token , context ) ;
238+ builder . Append ( ")" ) ;
239+ }
240+
208241 builder . Append ( fieldSuffix ) ;
209242 if ( i . IsLast )
210243 builder . Append ( ")" ) ;
@@ -220,6 +253,7 @@ public static string ToDynamicLinqString(this TermNode node, ISqlQueryVisitorCon
220253
221254 var field = GetFieldInfo ( context . Fields , node . Field ) ;
222255 var ( fieldPrefix , fieldSuffix ) = field . GetFieldPrefixAndSuffix ( ) ;
256+ var ( scopePrefix , argumentPrefix ) = SplitFieldPrefix ( field , fieldPrefix ) ;
223257 var searchOperator = SqlSearchOperator . Equals ;
224258 if ( node . Term . StartsWith ( "*" ) && node . Term . EndsWith ( "*" ) )
225259 searchOperator = SqlSearchOperator . Contains ;
@@ -231,28 +265,59 @@ public static string ToDynamicLinqString(this TermNode node, ISqlQueryVisitorCon
231265
232266 if ( searchOperator == SqlSearchOperator . Equals )
233267 {
234- builder . Append ( fieldPrefix ) ;
268+ builder . Append ( scopePrefix ) ;
269+ builder . Append ( argumentPrefix ) ;
235270 builder . Append ( field . Name ) ;
236271 builder . Append ( " = " ) ;
237272 AppendField ( builder , field , node . Term , context ) ;
238273 builder . Append ( fieldSuffix ) ;
239274 }
240275 else if ( searchOperator == SqlSearchOperator . Contains )
241276 {
242- builder . Append ( fieldPrefix ) ;
243- builder . Append ( field . Name ) ;
244- builder . Append ( ".Contains(" ) ;
245- AppendField ( builder , field , node . Term , context ) ;
246- builder . Append ( ")" ) ;
277+ builder . Append ( scopePrefix ) ;
278+
279+ if ( context . FullTextFields . Contains ( field . FullName , StringComparer . OrdinalIgnoreCase ) )
280+ {
281+ builder . Append ( "FTS.Contains(" ) ;
282+ builder . Append ( argumentPrefix ) ;
283+ builder . Append ( field . Name ) ;
284+ builder . Append ( ", " ) ;
285+ AppendField ( builder , field , node . Term , context ) ;
286+ builder . Append ( ")" ) ;
287+ }
288+ else
289+ {
290+ builder . Append ( argumentPrefix ) ;
291+ builder . Append ( field . Name ) ;
292+ builder . Append ( ".Contains(" ) ;
293+ AppendField ( builder , field , node . Term , context ) ;
294+ builder . Append ( ")" ) ;
295+ }
296+
247297 builder . Append ( fieldSuffix ) ;
248298 }
249299 else
250300 {
251- builder . Append ( fieldPrefix ) ;
252- builder . Append ( field . Name ) ;
253- builder . Append ( ".StartsWith(" ) ;
254- AppendField ( builder , field , node . Term , context ) ;
255- builder . Append ( ")" ) ;
301+ builder . Append ( scopePrefix ) ;
302+
303+ if ( context . FullTextFields . Contains ( field . FullName , StringComparer . OrdinalIgnoreCase ) )
304+ {
305+ builder . Append ( "FTS.Contains(" ) ;
306+ builder . Append ( argumentPrefix ) ;
307+ builder . Append ( field . Name ) ;
308+ builder . Append ( ", " ) ;
309+ AppendField ( builder , field , "\\ \" " + node . Term + "*\\ \" " , context ) ;
310+ builder . Append ( ")" ) ;
311+ }
312+ else
313+ {
314+ builder . Append ( argumentPrefix ) ;
315+ builder . Append ( field . Name ) ;
316+ builder . Append ( ".Contains(" ) ;
317+ AppendField ( builder , field , node . Term , context ) ;
318+ builder . Append ( ")" ) ;
319+ }
320+
256321 builder . Append ( fieldSuffix ) ;
257322 }
258323
@@ -277,6 +342,7 @@ public static string ToDynamicLinqString(this TermRangeNode node, ISqlQueryVisit
277342 context . AddValidationError ( "Field must be a number, money or date for term range queries." ) ;
278343
279344 var ( fieldPrefix , fieldSuffix ) = field . GetFieldPrefixAndSuffix ( ) ;
345+ var ( scopePrefix , argumentPrefix ) = SplitFieldPrefix ( field , fieldPrefix ) ;
280346
281347 var builder = new StringBuilder ( ) ;
282348
@@ -288,7 +354,8 @@ public static string ToDynamicLinqString(this TermRangeNode node, ISqlQueryVisit
288354
289355 if ( node . Min != null )
290356 {
291- builder . Append ( fieldPrefix ) ;
357+ builder . Append ( scopePrefix ) ;
358+ builder . Append ( argumentPrefix ) ;
292359 builder . Append ( field . Name ) ;
293360 builder . Append ( node . MinInclusive == true ? " >= " : " > " ) ;
294361 AppendField ( builder , field , node . Min , context ) ;
@@ -300,7 +367,8 @@ public static string ToDynamicLinqString(this TermRangeNode node, ISqlQueryVisit
300367
301368 if ( node . Max != null )
302369 {
303- builder . Append ( fieldPrefix ) ;
370+ builder . Append ( scopePrefix ) ;
371+ builder . Append ( argumentPrefix ) ;
304372 builder . Append ( field . Name ) ;
305373 builder . Append ( node . MaxInclusive == true ? " <= " : " < " ) ;
306374 AppendField ( builder , field , node . Max , context ) ;
@@ -335,6 +403,18 @@ public static EntityFieldInfo GetFieldInfo(List<EntityFieldInfo> fields, string
335403 new EntityFieldInfo { Name = field , FullName = field } ;
336404 }
337405
406+ private static ( string scopePrefix , string argumentPrefix ) SplitFieldPrefix ( EntityFieldInfo field , string fieldPrefix )
407+ {
408+ string navigationPrefix = field . GetNavigationPrefix ( ) ;
409+ if ( String . IsNullOrEmpty ( navigationPrefix ) )
410+ return ( fieldPrefix , String . Empty ) ;
411+
412+ if ( ! String . IsNullOrEmpty ( fieldPrefix ) && fieldPrefix . EndsWith ( navigationPrefix , StringComparison . Ordinal ) )
413+ fieldPrefix = fieldPrefix . Substring ( 0 , fieldPrefix . Length - navigationPrefix . Length ) ;
414+
415+ return ( fieldPrefix , navigationPrefix ) ;
416+ }
417+
338418 private static void AppendField ( StringBuilder builder , EntityFieldInfo field , string term , ISqlQueryVisitorContext context )
339419 {
340420 if ( field == null )
0 commit comments