Jos*_*wis 4 c# nhibernate nullreferenceexception queryover
我在NHibernate中使用JoinAlias QueryOver获得了一些意想不到的行为.
我的实体基本上是这样的:
public class Field
{
public virtual long Id { get; protected set; }
public virtual Field Parent { get; protected set; }
public virtual FieldType Type { get; protected set; }
public virtual string Value { get; protected set; }
...(Ctors etc
}
Run Code Online (Sandbox Code Playgroud)
我的映射是这样的:
public class FieldMap : ClassMap<Field>
{
public FieldMap()
{
Id(x => x.Id)
.GeneratedBy.Native();
References(x => x.Type)
.Column("FieldTypeId")
.LazyLoad()
.Cascade.All()
;
Map(x => x.Value);
References(x => x.Parent)
.Column("ParentFieldId")
.Nullable()
.LazyLoad()
.Cascade.All()
;
}
Run Code Online (Sandbox Code Playgroud)
我的查询:
Field fieldAlias = null;
string typeAlias = null;
Field parentFieldAlias = null;
var query = getSession().QueryOver<Field>(() => fieldAlias)
.JoinAlias(() => fieldAlias.Type, () => typeAlias)
.Where(() => typeAlias.Name == type)
.JoinAlias(() => fieldAlias.Parent, () => parentFieldAlias)
.Where(() => (parentFieldAlias.Value == parentValue) || (parentFieldAlias == null))
;
Run Code Online (Sandbox Code Playgroud)
就我而言,这应该给我一些像这样的SQL:
... WHERE(a.ParentFieldId == NULL)OR(a.ParentFieldId = c.FieldId AND c.Value = parentValue)
但我得到一个空引用异常.(我假设当别名被解析且Parent为null时).
例外细节是:
System.NullReferenceException occurred
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=NHibernate
StackTrace:
at NHibernate.Criterion.ConstantProjection..ctor(Object value)
at NHibernate.Criterion.Projections.Constant(Object obj)
at NHibernate.Impl.ExpressionProcessor.FindMemberProjection(Expression expression)
at NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression(Expression left, Expression right, ExpressionType nodeType)
at NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression(BinaryExpression be)
at NHibernate.Impl.ExpressionProcessor.ProcessBinaryExpression(BinaryExpression expression)
at NHibernate.Impl.ExpressionProcessor.ProcessExpression(Expression expression)
at NHibernate.Impl.ExpressionProcessor.ProcessOrExpression(BinaryExpression expression)
at NHibernate.Impl.ExpressionProcessor.ProcessBinaryExpression(BinaryExpression expression)
at NHibernate.Impl.ExpressionProcessor.ProcessExpression(Expression expression)
at NHibernate.Impl.ExpressionProcessor.ProcessLambdaExpression(LambdaExpression expression)
at NHibernate.Impl.ExpressionProcessor.ProcessExpression(Expression`1 expression)
at NHibernate.Criterion.QueryOver`2.Add(Expression`1 expression)
at NHibernate.Criterion.QueryOver`2.Where(Expression`1 expression)
at NHibernate.Criterion.QueryOver`2.NHibernate.IQueryOver<TRoot,TSubType>.Where(Expression`1 expression)
at Ismoos.Director.FieldOptionsQuery.Execute(Service service, String type, String parentValue) in D:\Work\Ismoos\Ismoos\Director\Ismoos.Director\FieldOptionsQuery.cs:line 31
InnerException:
Run Code Online (Sandbox Code Playgroud)
我尝试了几种不同的方式,包括:
.JoinAlias(() => fieldAlias.Parent, () => parentFieldAlias)
.Where(Restrictions.Or(Restrictions.On(() => fieldAlias.Parent).IsNotNull,
Restrictions.On(() => parentFieldAlias.Value).IsLike(parentValue))))
Run Code Online (Sandbox Code Playgroud)
但这些都不起作用.
我有一个解决方法,通过省略查询中父字段值的限制,并在QueryOver返回后执行LINQ查询,如下所示:
Field fieldAlias = null;
string typeAlias = null;
Field parentFieldAlias = null;
var query = getSession().QueryOver<Field>(() => fieldAlias)
.JoinAlias(() => fieldAlias.Type, () => typeAlias)
.Where(() => typeAlias.Name == type)
;
var list = query
.List<Field>()
;
return list
.Where(x => (x.Parent == null) || (x.Parent.Value == parentValue))
.ToList();
Run Code Online (Sandbox Code Playgroud)
但这并不像在QueryOver中那样优化.
有什么建议?
有限制的第二个解决方案可以胜任.有两个问题.我们需要LEFT JOIN到Parent,我看到一个错字:IsNotNull应该是IsNull正确评估OR声明:
破解IsNotNull(最有可能是内连接)
.JoinAlias(() => fieldAlias.Parent, () => parentFieldAlias)
.Where
(
Restrictions.Or(
Restrictions.On(() => fieldAlias.Parent).IsNotNull, // here
Restrictions.On(() => parentFieldAlias.Value).IsLike(parentValue)))
)
Run Code Online (Sandbox Code Playgroud)
工作OR与IsNull和LEFT JOIN:
.JoinAlias(() => fieldAlias.Parent, () => parentFieldAlias
, NHibernate.SqlCommand.JoinType.LeftOuterJoin)) // left join for NULL
.Where
(
Restrictions.Or(
Restrictions.On(() => fieldAlias.Parent).IsNull, // this is what we need
Restrictions.On(() => parentFieldAlias.Value).IsLike(parentValue))
);
Run Code Online (Sandbox Code Playgroud)
第一个解决方案的问题是,我们无法评估浮点/虚拟对象的 null :parentFieldAlias
.Where(()=>(parentFieldAlias.Value == parentValue)|| (parentFieldAlias == null));
我们需要检查所有者的财产: fieldAlias.Parent
| 归档时间: |
|
| 查看次数: |
6696 次 |
| 最近记录: |