Nhibernate无法删除具有null属性值的Value Object

时间:2017-03-28 14:09:45

标签: c# nhibernate null components

我遇到了nhibernate的这类问题:

当我尝试删除作为属性值的null的组件(没有ID的对象)时,操作失败,因为条件被翻译为field = NULL而不是Field IS NULL

我将RilevanzaFinding对象映射为Finding的组件:

HasMany<RilevanzaFinding>(x => x.Rilevanze)
        .Access.CamelCaseField(Prefix.Underscore)
        .Table("RilevanzaFinding_T045")
        .KeyColumn("int_T045_IdFinding")
        .Cascade.AllDeleteOrphan()
        .AsSet()
        .Component(fee =>
        {
            fee.References<Rating>(x => x.Rating).Column("int_T045_IdRating").Fetch.Join();
            fee.Map(x => x.DataFine)
                .Column("dte_T045_DataFine")                    
                .CustomSqlType("Date");
            fee.Map(x => x.Note)
                .Column("nvc_T045_Note")
                .Length(100000);
        });

public class Finding : BaseObject<Finding, int>
{
    private ICollection<RilevanzaFinding> _rilevanze = new List<RilevanzaFinding>();
    public virtual IEnumerable<RilevanzaFinding> Rilevanze
    {
        get
        {
            return _rilevanze.ToArray();
        }
    }
}

public class RilevanzaFinding : EquatableObject<RilevanzaFinding>
{
    public virtual Rating Rating { get; set; }
    public virtual DateTime? DataFine{ get; set; }
    public virtual string Note { get; set; }
}

其中EquatableObject实现此Equals:

public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        TObject other = obj as TObject;

        return Equals(other);

    }

    public virtual bool Equals(TObject other)
    {
        if (other == null)
            return false;

        Type t = GetType();

        TypeInfo typeInfo = t.GetTypeInfo();            
        IEnumerable<FieldInfo> fields = typeInfo.DeclaredFields.Where(x => x.FieldType.Name != typeof(ICollection<>).Name); 
        foreach (FieldInfo field in fields)
        {
            object value1 = field.GetValue(other);
            object value2 = field.GetValue(this);

            if (value1 == null)
            {
                if (value2 != null)
                    return false;
            }
            else if (!value1.Equals(value2))
                return false;
        }
        return true;
    }

现在当我从一个发现的集合中删除Rilevanza时,Rilevanze是由nhibernate生成的sql:

NHibernate: DELETE FROM RilevanzaFinding_T045 WHERE int_T045_IdFinding = 
@p0 AND dte_T045_DataFine = @p1 AND nvc_T045_Note = @p2 AND int_T045_IdRating
 = @p3;@p0 = 201 [Type: Int32 (0:0:0)], @p1 = NULL [Type: DateTime (0:0:0)], @p2 = 'GD675PFN2GTR9EUJ3JHPG7XFX' [Type: String (1073741823:0:0)], 
@p3 = 243 [Type: Int32 (0:0:0)]

"dte_T045_DataFine = NULL"条件而失败,因为它会"dte_T045_DataFine IS NULL"

我怎样才能让它写出正确的条件?

1 个答案:

答案 0 :(得分:1)

你不能使用set和NHibernate v5.1或前者。

来自NHibernate reference documentation (v5.1 and below)

  

请注意,复合元素映射不支持null   属性如果您使用的是<set>。 NHibernate必须使用每个列   删除对象时标识记录的值(没有单独的   复合元素表中的主键列),而不是   可以使用空值。您必须只使用非null   复合元素中的属性或选择<list><map><bag>或   <idbag>

在我看来,更好地映射实体而不是本案例的组件,并在表中添加主键。顺便说一句,你的SQL会表现得更好。

从NHibernate v4.1开始,使用NH-3634过滤查询的空等等语义支持。但仍然不支持删除案例。

从NHibernate v5.2(应该在2018年,Q3中可用),删除案例现在也支持它(#1170)。

另一个解决方案是升级到NHibernate v5.2。