我在照片和标签之间存在多对多关系:一张照片可以有多个标签,而多张照片可以共享相同的标签。

我有一个循环,它扫描目录中的照片,然后将它们添加到NHibernate中。在此过程中,一些标签会添加到照片中,例如2009年照片拍摄时的2009年标签。

Tag类实现Equals和GetHashCode,并将Name属性用作唯一的签名属性。 “照片”和“标签”都具有代理键,并已版本化。

我有一些类似于以下内容的代码:

public void Import() {
    ...
    foreach (var fileName in fileNames) {
        var photo = new Photo { FileName = fileName };
        AddDefaultTags(_session, photo, fileName);
        _session.Save(photo);
    }
    ...
}

private void AddDefaultTags(…) {
    ...
    var tag =_session.CreateCriteria(typeof(Tag))
                    .Add(Restriction.Eq(“Name”, year.ToString()))
                    .UniqueResult<Tag>();

    if (tag != null) {
        photo.AddTag(tag);
    } else {
        var tag = new Tag { Name = year.ToString()) };
        _session.Save(tag);
        photo.AddTag(tag);
    }
}


我的问题是标签不存在时,例如新年的第一张照片。 AddDefaultTags方法检查数据库中是否存在该标记,然后创建该标记并将其添加到NHibernate。添加一张照片时效果很好,但是在新的一年中以及在同一工作单元中导入多张照片时,它失败了,因为该照片在数据库中仍然不存在并被重新添加。完成工作单元后,它会失败,因为它试图在“标签”表中添加两个具有相同名称的条目...

我的问题是在上述情况下如何确保NHibernate仅尝试在数据库中创建单个标签。我需要自己维护一个新添加标签的列表,还是可以以一种可行的方式设置映射?

最佳答案

如果您的条件不应返回过时的数据,则需要运行_session.Flush()
或者,您也可以通过将_session.FlushMode设置为“自动”来正确执行此操作。

使用FlushMode.Auto,将在执行条件之前自动刷新会话。

编辑:并且重要!阅读显示的代码时,您似乎无法在工作单元中使用事务。我建议将您的工作单元包装在事务中-如果您使用的是NH2.0 +,这是FlushMode.Auto正常工作所必需的!

在此处进一步阅读:NHibernate ISession Flush: Where and when to use it, and why?

07-28 02:12
查看更多