gpt4 book ai didi

c# - 带有空测试的 NHibernate JoinAlias 查询不起作用

转载 作者:太空狗 更新时间:2023-10-30 00:33:06 24 4
gpt4 key购买 nike

我在 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
}

我的映射是这样的:

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()
;
}

我的查询:

        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))
;

就我而言,这应该给我一些像这样的 SQL:

... WHERE (a.ParentFieldId == NULL) 或 (a.ParentFieldId = c.FieldId AND c.Value = parentValue)

但是我遇到了空引用异常。 (我假设当别名被解析并且 Parent 为空时)。

异常详细信息是:

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:

我尝试了几种不同的方法,包括:

            .JoinAlias(() => fieldAlias.Parent, () => parentFieldAlias)
.Where(Restrictions.Or(Restrictions.On(() => fieldAlias.Parent).IsNotNull,
Restrictions.On(() => parentFieldAlias.Value).IsLike(parentValue))))

但这些都不起作用。

我有一个解决方法,通过在查询中省略对父字段值的限制,并在 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();

但这并不像在 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)))
)

使用 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))
);

第一个解决方案的问题是,我们无法评估 float /虚拟对象是否为空:parentFieldAlias

.Where(() => (parentFieldAlias.Value == parentValue) ||(parentFieldAlias == null)) ;

我们需要检查所有者的属性:fieldAlias.Parent

关于c# - 带有空测试的 NHibernate JoinAlias 查询不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13672448/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com