NHibernate,添加child时添加父项(如果不存在)

时间:2018-04-21 14:59:13

标签: c# sqlite nhibernate

我使用此代码来确定它是否应该创建父代,或者父代是否已经存在:

var id = 1;
var parent = Session.Get<Parent>(id);

if (parent == null)
  parent = new Parent();

var child = new Child();

child.Parent = parent;
parent.Children.Add(child);

Session.Save(parent);

现在这看起来非常低效,这个方法每次添加子项时都会使用3个单独的sql查询来查询数据库:

  1. 根据ID
  2. 获取父级
  3. 插入儿童
  4. 插入/更新父级(取决于父级是否存在)
  5. 我能以更好的方式做到这一点吗?

2 个答案:

答案 0 :(得分:2)

事实上有两种情况。

在第一种情况下,当我们确实不知道时,如果父母提供了 id - 则没有别的办法。这样的解决方案总是需要这么多的 sql语句..来确定是否存在父级,如果没有则插入。

在第二种情况下,如果我们确实知道数据库中有父级(提供了​​ id ) - 我们可以通过内置支持提高效率:Load<Parent>(id)

9.2. Loading an object

  

... Load()返回一个未初始化的代理对象   实际上没有命中数据库,直到你调用一个方法   对象...

在此处获取更多详细信息:

NHibernate difference between Query<T>, Get<T> and Load<T>

答案 1 :(得分:2)

鉴于您处于常规业务逻辑开发阶段,我不会介意这些查询。

Get非常快,因为它通常通过主键执行查找,主键通常是聚簇索引(不了解SQLite)。

无论如何,需要找到现有的父母。您可以使用Load推迟实际查询,但根据我的经验,您仍然需要父级。

更新父级可能是不必要的。什么更新?是否缺少逆映射?

如果你正在为很多记录(不仅仅是一个)做整件事,你可以考虑其他选择。 (批次,预​​取,期货,等等。)

如果您认为您需要针对此代码的高度优化实现,则应考虑避免使用ORM并在纯SQL中实现它(并重新检查它是否真的使用较少的查询)。编写面向对象的代码需要在内存中包含对象,有时需要从数据库中获取高度优化的实现中不需要的数据。