我在使用 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/