Nhibernate where子串错误
Nhibernate where substring error
我有一个这样的工作查询:
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 但我需要使用它(或 Substring),则不会发生这种情况。
P.S。我正在使用 Nhibernate 4.0.3 GA
不幸的是,.SubStr
扩展方法不够强大,无法处理常量值以外的任何参数。
幸运的是,您可以通过使用 Projections.SqlFunction
并以这种方式调用 substring
方法来解决这个问题。您还需要添加一个可以执行减法的函数,因为不幸的是您不能使用内置的 QueryOver 功能执行算术运算。
首先,创建一个包含您的自定义投影的静态 class:
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();
我有一个这样的工作查询:
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 但我需要使用它(或 Substring),则不会发生这种情况。
P.S。我正在使用 Nhibernate 4.0.3 GA
不幸的是,.SubStr
扩展方法不够强大,无法处理常量值以外的任何参数。
幸运的是,您可以通过使用 Projections.SqlFunction
并以这种方式调用 substring
方法来解决这个问题。您还需要添加一个可以执行减法的函数,因为不幸的是您不能使用内置的 QueryOver 功能执行算术运算。
首先,创建一个包含您的自定义投影的静态 class:
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();