c# - Nhibernate 无法删除具有空属性值的值对象

标签 c# nhibernate null components

我在使用 nhibernate 时遇到过这类问题:

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

我将 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;
    }

现在,当我从发现 Rilevanze 的集合中删除 Rilevanza 时,这是 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"

如何让它写入正确的条件?

最佳答案

你不能用 set和 NHibernate v5.1 或更早版本。

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

Please note that a composite element mapping doesn't support null-able properties if you're using a <set>. NHibernate has to use each columns value to identify a record when deleting objects (there is no separate primary key column in the composite element table), which is not possible with null values. You have to either use only not-null properties in a composite-element or choose a <list>, <map>, <bag> or <idbag>.

在我看来,对于这种情况,最好映射一个实体而不是一个组件,并向您的表添加一个主键。顺便说一下,您的 SQL 会执行得更好。


从 NHibernate v4.1 开始,空值相等语义支持被添加到使用 NH-3634 的过滤查询中.但是仍然不支持删除大小写。

从 NHibernate v5.2(应该在 2018 年第 3 季度可用)开始,删除大小写现在也支持它(#1170)。

所以另一种解决方案是升级到 NHibernate v5.2。

关于c# - Nhibernate 无法删除具有空属性值的值对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43071870/

相关文章:

c# - 用于处理关系/连接表插入的 Web 服务器控件

nhibernate - Fluent nHIbernated - 在同一张表中有许多关系

performance - LLBLGen Pro 如何与 Nhibernate 性能相提并论

c - strcat() 和 read() 如何处理 C 中的 '\0'

c# - 根据 Msdn GridView.DataKeyNames 必须设置,如果我们想更新数据库

c# - jquery改变后如何获取HtmlDocument? (HtmlAgilityPack)

android - 当 PriorityQueue.size() > 0 时,为什么 PriorityQueue.peek() 返回 null

带有空列的 MySQL 内部连接

c# - 是否有什么东西阻止 Response.Redirect 在 try-catch block 内工作?

NHibernate 投影帮助