c# - Custom SQLFunctionTemplate on XML field causes escaping error if a Skip(..) LINQ section follows -


i have created custom sqlfunctiontemplate query xml field specific name/value pairs:

registerfunction("_existincaratteristiche",                  new sqlfunctiontemplate(nhibernateutil.boolean,                      "?1.exist('/l/i/c[n=sql:variable(\"?2\") , v=sql:variable(\"?3\")]') = 1")); 

which use this:

private iqueryable<myentity> _xmlfilter(iqueryable<myentity> input, string element, string value)         {             if (string.isnullorempty(element) || string.isnullorempty(value))                 return input;              return input.where(m => m.xmlfield.xmlcontains(element.toupper(),value));         } 

and so, can do:

.. iqueryable<myentity> result = session.query<myentity>();              result = _xmlfilter(result, filter.element, filter.value);             return result.tolist();     .. 

this working correctly.

unfortunately, if add skip linq section after custom filter, this:

.. iqueryable<myentity> result = session.query<myentity>();              result = _xmlfilter(result, filter.element, filter.value);             result = result.skip(3);             return result.tolist();     .. 

i following error when result.tolist() called:

cannot find terminating ''' character quoted text.

i think i'm facing escaping problem have no idea why happens if add skip linq section. tried various combinations of quotes , single quotes in sqlfunctiontemplate wasn't able solve issue.

as requested oskar berggren, here's full stack-trace of exception, thrown nhibernate tries convert iqueryable appropriate query (which when .tolist() invoked)

nhibernate.exceptions.sqlparseexception: cannot find terminating ''' character quoted text.    @ nhibernate.sqlcommand.parser.sqlparserutils.readdelimitedtext(string text, int32 maxoffset, int32 offset)    @ nhibernate.sqlcommand.parser.sqltokenizer.<getenumerator>d__0.movenext()    @ nhibernate.sqlcommand.parser.sqltokenizerextensions.tryparseuntil(ienumerator`1 tokenenum, string keyword)    @ nhibernate.sqlcommand.parser.sqltokenizerextensions.tryparseuntilfirstordercolumn(ienumerator`1 tokenenum, sqltoken& ordertoken)    @ nhibernate.sqlcommand.parser.mssqlselectparser..ctor(sqlstring sql)    @ nhibernate.dialect.mssql2005dialectquerypager.pagebylimitandoffset(sqlstring offset, sqlstring limit)    @ nhibernate.dialect.mssql2005dialectquerypager.pageby(sqlstring offset, sqlstring limit)    @ nhibernate.dialect.mssql2005dialect.getlimitstring(sqlstring querystring, sqlstring offset, sqlstring limit)    @ nhibernate.dialect.dialect.getlimitstring(sqlstring querystring, nullable`1 offset, nullable`1 limit, parameter offsetparameter, parameter limitparameter)    @ nhibernate.hql.ast.antlr.sqlgenerator.getsqlstringwithlimitsifneeded(querywriter querywriter)    @ nhibernate.hql.ast.antlr.sqlgenerator.endquery()    @ nhibernate.hql.ast.antlr.sqlgenerator.selectstatement()    @ nhibernate.hql.ast.antlr.sqlgenerator.statement()    @ nhibernate.hql.ast.antlr.hqlsqlgenerator.generate()    @ nhibernate.hql.ast.antlr.querytranslatorimpl.docompile(idictionary`2 replacements, boolean shallow, string collectionrole)    @ nhibernate.hql.ast.antlr.querytranslatorimpl.compile(idictionary`2 replacements, boolean shallow)    @ nhibernate.hql.ast.antlr.astquerytranslatorfactory.createquerytranslators(iastnode ast, string queryidentifier, string collectionrole, boolean shallow, idictionary`2 filters, isessionfactoryimplementor factory)    @ nhibernate.hql.ast.antlr.astquerytranslatorfactory.createquerytranslators(iqueryexpression queryexpression, string collectionrole, boolean shallow, idictionary`2 filters, isessionfactoryimplementor factory)    @ nhibernate.engine.query.queryexpressionplan.createtranslators(iqueryexpression queryexpression, string collectionrole, boolean shallow, idictionary`2 enabledfilters, isessionfactoryimplementor factory)    @ nhibernate.engine.query.queryexpressionplan..ctor(iqueryexpression queryexpression, boolean shallow, idictionary`2 enabledfilters, isessionfactoryimplementor factory)    @ nhibernate.engine.query.queryplancache.gethqlqueryplan(iqueryexpression queryexpression, boolean shallow, idictionary`2 enabledfilters)    @ nhibernate.impl.abstractsessionimpl.gethqlqueryplan(iqueryexpression queryexpression, boolean shallow)    @ nhibernate.impl.abstractsessionimpl.createquery(iqueryexpression queryexpression)    @ nhibernate.linq.defaultqueryprovider.preparequery(expression expression, iquery& query, nhlinqexpression& nhquery)    @ nhibernate.linq.defaultqueryprovider.execute(expression expression)    @ nhibernate.linq.defaultqueryprovider.execute[tresult](expression expression)    @ remotion.linq.queryablebase`1.getenumerator()    @ system.collections.generic.list`1..ctor(ienumerable`1 collection)    @ system.linq.enumerable.tolist[tsource](ienumerable`1 source)    @ trim.chibro.services.base.operations.listodpoperation.execute(listodpdto filter) in c:\progetti.svn.cloud\chibro\chibromes\src\trim.chibro.services\base\operations\listodpoperation.cs:line 30    @ trim.chibro.services.implementations.listodpservice.execute(listodpdto filter) in c:\progetti.svn.cloud\chibro\chibromes\src\trim.chibro.services\implementations\listodpservice.cs:line 20    @ trim.chibro.web.controllers.listodpcontroller.index(listodpmodel model) in c:\progetti.svn.cloud\chibro\chibromes\src\trim.chibro.web\controllers\listodpcontroller.cs:line 75    @ lambda_method(closure , controllerbase , object[] )    @ system.web.mvc.actionmethoddispatcher.execute(controllerbase controller, object[] parameters)    @ system.web.mvc.reflectedactiondescriptor.execute(controllercontext controllercontext, idictionary`2 parameters)    @ system.web.mvc.controlleractioninvoker.invokeactionmethod(controllercontext controllercontext, actiondescriptor actiondescriptor, idictionary`2 parameters)    @ system.web.mvc.async.asynccontrolleractioninvoker.actioninvocation.invokesynchronousactionmethod()    @ system.web.mvc.async.asynccontrolleractioninvoker.<begininvokesynchronousactionmethod>b__39(iasyncresult asyncresult, actioninvocation innerinvokestate)    @ system.web.mvc.async.asyncresultwrapper.wrappedasyncresult`2.callenddelegate(iasyncresult asyncresult)    @ system.web.mvc.async.asyncresultwrapper.wrappedasyncresultbase`1.end()    @ system.web.mvc.async.asyncresultwrapper.end[tresult](iasyncresult asyncresult, object tag)    @ system.web.mvc.async.asynccontrolleractioninvoker.endinvokeactionmethod(iasyncresult asyncresult)    @ system.web.mvc.async.asynccontrolleractioninvoker.asyncinvocationwithfilters.<invokeactionmethodfilterasynchronouslyrecursive>b__3d()    @ system.web.mvc.async.asynccontrolleractioninvoker.asyncinvocationwithfilters.<>c__displayclass46.<invokeactionmethodfilterasynchronouslyrecursive>b__3f()    @ system.web.mvc.async.asynccontrolleractioninvoker.<>c__displayclass33.<begininvokeactionmethodwithfilters>b__32(iasyncresult asyncresult)    @ system.web.mvc.async.asyncresultwrapper.wrappedasyncresult`1.callenddelegate(iasyncresult asyncresult)    @ system.web.mvc.async.asyncresultwrapper.wrappedasyncresultbase`1.end()    @ system.web.mvc.async.asyncresultwrapper.end[tresult](iasyncresult asyncresult, object tag)    @ system.web.mvc.async.asynccontrolleractioninvoker.endinvokeactionmethodwithfilters(iasyncresult asyncresult)    @ system.web.mvc.async.asynccontrolleractioninvoker.<>c__displayclass21.<>c__displayclass2b.<begininvokeaction>b__1c()    @ system.web.mvc.async.asynccontrolleractioninvoker.<>c__displayclass21.<begininvokeaction>b__1e(iasyncresult asyncresult) 

in stack trace can see problem comes within getlimitstring() , helpers, answers question why happens skip() present. if there no skip/take there no reason apply limit/offset sql , therefore method never called.

as problem it's bit difficult. nhibernate has magic sql apply limit/offset mssql dialects before 2012 since lack straightforward sql syntax feature.

i can't tell if there problem escaping in code, or if hitting case nhibernate's mssqlselectparser wasn't designed.

if grab nhibernate source code , pdb-file, can try debugging down top 5 lines of stack trace , step trough see goes wrong.


Comments