2015-01-21 3 views
2

У меня есть рабочий запрос, как это:Nhibernate где ошибка подстрока

SELECT this_.ID, this_.NomeFile, this_.DataGenerazioneFile, esitiopera_.ID, esitiopera_.Date, esitiopera_.ID_FileTelematico 
FROM FileTelematico this_ 
LEFT OUTER JOIN EsitoOperazione esitiopera_ ON this_.ID = esitiopera_.ID_FileTelematico 
WHERE SUBSTRING (this_.NomeFile, 1, LEN(this_.NomeFile)-4) 
IN ('filename1', 'filename2', 'filename3') 
ORDER BY this_.DataGenerazioneFile DESC; 

, и я пытаюсь написать то же самое с QueryOver

FileTelematico ft = null; 
string[] nomi = {'filename1', 'filename2', 'filename3'} 
var files = session.QueryOver<FileTelematico>(() => ft)      
      .Where(() => ft.NomeFile.Substr(1, ft.NomeFile.StrLength() -4) 
      .IsIn(nomi)) 
      .Fetch(x => x.EsitiOperazioni).Eager 
      .OrderBy(() => ft.DataGenerazioneFile).Desc 
      .List() 

, но это только конец с System.NullReferenceException

in System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) 
    in System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) 
    in System.Delegate.DynamicInvokeImpl(Object[] args) 
    in System.Delegate.DynamicInvoke(Object[] args) 
    in NHibernate.Impl.ExpressionProcessor.FindValue(Expression expression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Impl\ExpressionProcessor.cs:riga 248 
    in NHibernate.Impl.ExpressionProcessor.FindMemberProjection(Expression expression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Impl\ExpressionProcessor.cs:riga 258 
    in NHibernate.Criterion.RestrictionExtensions.ProcessIsInCollection(MethodCallExpression methodCallExpression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Criterion\RestrictionsExtensions.cs:riga 138 
    in NHibernate.Impl.ExpressionProcessor.ProcessCustomMethodCall(MethodCallExpression methodCallExpression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Impl\ExpressionProcessor.cs:riga 662 
    in NHibernate.Impl.ExpressionProcessor.ProcessBooleanExpression(Expression expression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Impl\ExpressionProcessor.cs:riga 620 
    in NHibernate.Impl.ExpressionProcessor.ProcessExpression(Expression expression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Impl\ExpressionProcessor.cs:riga 671 
    in NHibernate.Impl.ExpressionProcessor.ProcessLambdaExpression(LambdaExpression expression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Impl\ExpressionProcessor.cs:riga 676 
    in NHibernate.Impl.ExpressionProcessor.ProcessExpression(Expression`1 expression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Impl\ExpressionProcessor.cs:riga 697 
    in NHibernate.Criterion.QueryOver`2.Add(Expression`1 expression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Criterion\QueryOver.cs:riga 755 
    in NHibernate.Criterion.QueryOver`2.Where(Expression`1 expression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Criterion\QueryOver.cs:riga 362 
    in NHibernate.Criterion.QueryOver`2.NHibernate.IQueryOver<TRoot,TSubType>.Where(Expression`1 expression) in d:\Projects\NHibernate\nhibernate-core\src\NHibernate\Criterion\QueryOver.cs:riga 803 
    in 

это не произойдет, если я не использую Substr, но мне нужно использовать его (или подстроку).

P.S. Я использую Nhibernate 4.0.3 GA

ответ

1

К сожалению, метод расширения .SubStr не обладает достаточной мощью, чтобы обрабатывать все, кроме постоянных значений, в качестве аргументов.

К счастью, вы можете обойти это, используя Projections.SqlFunction и вместо этого вызывая метод substring. Вам также необходимо добавить функцию, которая может делать вычитание, поскольку, к сожалению, вы не можете выполнять арифметические операции со встроенными функциями QueryOver.

Во-первых, создать статический класс, который содержит пользовательские проекции:

public static class CustomProjections 
{ 
    public static IProjection Subtract(IProjection one, IProjection other) 
    { 
     return Projections.SqlFunction(
      new VarArgsSQLFunction(NHibernateUtil.Int32, "(", "-", ")"), 
      NHibernateUtil.Int32, 
      one, 
      other); 
    } 

    public static IProjection SubStr(IProjection prop, IProjection start, IProjection end) 
    { 
     return Projections.SqlFunction(
      "substring", 
      NHibernateUtil.String, 
      prop, 
      start, 
      end); 
    } 

    public static IProjection Length(IProjection prop) 
    { 
     return Projections.SqlFunction(
      "length", 
      NHibernateUtil.Int32, 
      prop); 
    } 
} 

Далее используйте Restrictions.In и использовать пользовательские проекции, передавая результат проекции Length на SubStr:

FileTelematico ft = null; 

session.QueryOver<FileTelematico>(() => ft) 
    .Where(
     Restrictions.In(
      CustomProjections.SubStr(
       Projections.Property(() => ft.NomeFile), 
       Projections.Constant(1), 
       CustomProjections.Subtract(
        CustomProjections.Length(
         Projections.Property(() => ft.NomeFile)), 
         Projections.Constant(4))), 
      nomi)) 
    .Fetch(x => x.EsitiOperazioni).Eager 
    .OrderBy(() => ft.DataGenerazioneFile).Desc 
    .List(); 

Вид грязный, но должен выполнить свою работу.

Вы можете очистить это немного, если вы хотите, чтобы рефакторинга различные части .Where вызова в переменных:

FileTelematico ft = null; 

IProjection length = 
    CustomProjections.Subtract(
     CustomProjections.Length(Projections.Property(() => ft.NomeFile)), 
     Projections.Constant(4)); 

IProjection substring = 
    CustomProjections.SubStr(
     Projections.Property(() => ft.NomeFile), 
     Projections.Constant(1), 
     length); 

AbstractCriterion inRestriction = 
    Restrictions.In(substring, nomi); 


session.QueryOver<FileTelematico>(() => ft) 
    .Where(inRestriction) 
    .Fetch(x => x.EsitiOperazioni).Eager 
    .OrderBy(() => ft.DataGenerazioneFile).Desc 
    .List(); 
+0

Спасибо большое, это написать правильный SQL, но если я не могу использовать этот : 'LEN (this_.NomeFile) - 4' и кажется, что этого не может быть, нет такого запроса. – Shyguy

+0

@Shyguy: Мне очень жаль, я полностью пропустил часть '- 4'. Я исправлю это и обновить ответ. –

+0

@Shyguy: см. Мои обновления –

Смежные вопросы