4

我目前在更新实体上的组件集合时遇到问题。它最初被映射为一个包,但这会导致所有条目每次都被删除并重新插入。将其更改为一组已解决该问题,但引入了一个新问题。

组件类型被称为Tracking它有一个复合键UserIDItemID和两个可以为空的日期属性。当其中一个被创建DateRead设置为当前时间时,稍后会用新日期的条目替换它。

NHibernate 生成的底层 SQL 有一个 where 子句,用于检查所有属性是否匹配。

问题是,其他日期DateAcknowledged通常为空,并且生成的 SQL 似乎有语法错误,要进行空检查,它会这样做: = NULL而不是:IS NULL,如图所示:

DELETE FROM TrackingTable
   WHERE  ItemId = 'a68f6dea-1c00-42e2-bc40-9fcf01121bd8' /* @p0 */
   AND UserId = 'c8aa41a4-e4c2-4347-ae6e-b48738a53b47' /* @p1 */
   AND DateRead = '2012-01-26T12:56:46.00' /* @p2 */
   AND DateAcknowledged = NULL /* @p3 */

问题是,根本不需要这两个日期来确定要删除的内容。只需在 where 检查项目 ID 和用户 ID 即可。

这是我定义集合的映射代码:

Set(x => x.Trackings,
         mapper =>
                {
                    mapper.Key(k => k.Column("ItemId"));
                    mapper.Table("Tracking");
                    mapper.Access(Accessor.NoSetter);
                },
                collectionMapping => collectionMapping.Component(TrackingMap.Mapping()));

这是组件的映射:

public class TrackingMap
    {
        public static Action<IComponentElementMapper<Tracking>> Mapping()
        {
            return c =>
            {
                c.ManyToOne(x => x.User, a => { a.Column("UserId"); a.ForeignKey("UserId"); });
                c.Property(x => x.DateRead);
                c.Property(x => x.DateAcknowledged, a => a.NotNullable(false));
            };
        }
    }

有没有办法告诉 NHibernate 只在 where 子句上使用键,或者让它以正确的方式比较空值?

4

2 回答 2

2

第7.2节对此进行了介绍。不支持的依赖对象的集合:

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

于 2012-05-30T18:13:24.490 回答
1

有关如何使用标准删除 NHibernate 实体的详细说明,请参阅此答案。这应该允许您仅在确定要删除的项目时使用并安全地忽略日期比较ItemIdUserId

于 2012-01-26T14:42:53.167 回答