如何持久化对象的子集而不是整个对象?

Jun*_*der 10 nhibernate nhibernate-mapping

我正在努力解决NHibernate相关的问题,我可以使用一些输入.

介绍:

我有一个遗留数据库,其中关系概念尚未真正应用.

在数据库中,我有一个OrderLine表,其中包含订单行的数据.

最重要的是,该表还包含具有Order特定信息的所有列.例如,这可以是客户的订单号.

例如,如果我有10个订单行 - 那么我的OrderLines表中有10行,每行都有所有Order特定数据,例如订单号或客户信息.

我不想在我的代码中使用上面的结构,因此创建了一个视图,Orders以便我可以Order在NHibernate中映射我的NHibernate,然后有一个OrderLines更有意义的set/bag .

映射:(简化)

<class name="Order" table="[view_Orders]">
    <bag name="OrderLines">
</class>

<class name="OrderLine" table="OrderLines" />
Run Code Online (Sandbox Code Playgroud)

问题:

视图的复杂性使得无法保存到视图中.尝试NHibernates时抛出此异常:

NHibernate.Exceptions.GenericADOException:无法插入:XXX ---> System.Data.SqlClient.SqlException:视图或函数'view_Orders'不可更新,因为修改会影响多个基表.

我的NHibernate映射被构造为一个Order具有"集合或包" OrderLine对象的对象.理想情况下,我希望NHibernate只保留OrderLine对象集而不是整个对象.

有没有办法实现这个目标?我尝试使用不同的锁定模式锁定对象,但它没有帮助我.

Rad*_*ler 1

如果我确实理解您的问题,那么解决方案非常简单。我们只需标记根对象dynamic-update="true"

<class name="Order" table="[view_Orders]" dynamic-update="true">
    ...
</class>
Run Code Online (Sandbox Code Playgroud)

然后应用于update="false"该类中映射到视图的每个属性或引用Order

...
<property name="Code"       update="false"/>
...
<many-to-one name="Country" update="false />
Run Code Online (Sandbox Code Playgroud)

但我们的集合将需要标准的,甚至级联映射:

<class name="Order" table="[view_Orders]" dynamic-update="true">
    <bag name="OrderLines" 
         lazy="true" 
         inverse="true" 
         batch-size="25" 
         cascade="all-delete-orphan" >
      ...
     </bag>
     ... // other stuff is update="false"
</class>
Run Code Online (Sandbox Code Playgroud)

现在像这样的代码将进行管理OrderLines,而不对根对象执行任何更新Order

var session = ... // get ISession 
// load root
var root = session.Get<Order>(123);

// if needed change existing line (pretend there is one)
root.OrderLines[0].Amount = 100;

// add new
var newOrder = ... // new order
root.OrderLines.Add(newOrder);

session.Save(root);
session.Flush();
Run Code Online (Sandbox Code Playgroud)

就是这样。根对象上的级联正在执行我们需要的操作,而 update="false" 则没有更新它......

注意:只是有趣的注释 - 还有类和集合设置mutable="false",但它在这里不起作用...正如上面提到的解决方案(很遗憾,因为这会更优雅,但不能按预期工作...)。看:

19.2.2。策略:只读

如果您的应用程序需要读取但从不修改持久类的实例,则可以使用只读缓存。这是最简单且效果最好的策略。在集群中使用甚至是完全安全的。

<class name="Eg.Immutable" mutable="false">