NHibernate Issues之1899:ISession.SaveOrUpdateCopy()方法
本节内容
概览
这个系列是以博客形式整理关于NHibernate的Issues。记录一些零碎的小例子,通过零零碎碎的整理,可以巩固自己的知识和扩展我们的知识面。这些小例子也可以适当的在项目中呈现。
这次看看ISession.SaveOrUpdateCopy()方法。
实例
这个小例子可以分析到这个方法的使用。
1.Domain
定义一Domain,关联一些字典。
public class Parent { public virtual int Id { get; set; } public virtual IDictionary<Key, Value> Relations { get; set; } } public enum Key { One, Two } public enum Value { ValOne, ValTwo }
2.Mapping
使用Map映射字典类型,在RelationsTable表中,级联所有和删除孤单节点。
<class name="Parent"> <id name="Id"> <generator class="assigned" /> </id> <map name="Relations" table="RelationsTable" cascade="all-delete-orphan"> <key column="ParentID" /> <index column="KeyId" type="Key" /> <element column="Value" type="Value" /> </map> </class>
3.Test
在第一个Session中保存这个Domain,在第二个Session中获取这个Domain并关闭销毁这个Session,在第三个Session中保存或者更新复制这个Domain。
using (var session = OpenSession()) { var entityDomain = new Parent { Id = 1, Relations = new Dictionary<Key, Value> { {Key.One, Value.ValOne}, {Key.Two, Value.ValTwo} } }; session.Save(entityDomain); session.Flush(); } Parent entity; using (var session = OpenSession()) { entity = session.Get<Parent>(1); session.Close(); session.Dispose(); } using (var session2 = OpenSession()) { entity = (Parent)session2.SaveOrUpdateCopy(entity); }
4.结果
看看上面测试输出的SQL语句吧,一清二楚:
--插入数据 INSERT INTO Parent (Id) VALUES (@p0);@p0 = 1 INSERT INTO RelationsTable (ParentID, KeyId, Value) VALUES (@p0, @p1, @p2);@p0 = 1, @p1 = 0, @p2 = 0 INSERT INTO RelationsTable (ParentID, KeyId, Value) VALUES (@p0, @p1, @p2);@p0 = 1, @p1 = 1, @p2 = 1 --ISession.Get()方法 SELECT parent0_.Id as Id0_0_ FROM Parent parent0_ WHERE parent0_.Id=@p0;@p0 = 1 --ISession.SaveOrUpdateCopy()方法 SELECT parent0_.Id as Id0_0_, relations1_.ParentID as ParentID2_, relations1_.Value as Value2_, relations1_.KeyId as KeyId2_ FROM Parent parent0_ left outer join RelationsTable relations1_ on parent0_.Id=relations1_.ParentID WHERE parent0_.Id=@p0;@p0 = 1
分析
在NHibernate API文档中对ISession.SaveOrUpdateCopy()方法这样的解释:
Name | Description |
---|---|
SaveOrUpdateCopy(Object) |
Copy the state of the given object onto the persistent object with
the same identifier. If there is no persistent instance currently
associated with the session, it will be loaded. Return the
persistent instance. If the given instance is unsaved or does not
exist in the database, save it and return it as a newly persistent
instance. Otherwise, the given instance does not become associated
with the session.
|
SaveOrUpdateCopy(Object, Object) |
Copy the state of the given object onto the persistent object with
the given identifier. If there is no persistent instance currently
associated with the session, it will be loaded. Return the
persistent instance. If there is no database row with the given
identifier, save the given instance and return it as a newly
persistent instance. Otherwise, the given instance does not become
associated with the session.
|
简单的就是说:将传入的对象的状态也就是属性赋给Session缓存中相同键值的对象上,如果该对象不存在则从数据库加载,传入的对象并不进行持久化。如果数据库不存在这个对象,则进行保存。
所以,当我们调用ISession.SaveOrUpdateCopy()方法时,先把传的对象赋值到新的对象(如果传的参数为空,则抛出“attempt to create merge event with null entity”异常),然后发出一条SQL查询数据库:
- 数据库里有这个对象并相同,什么都不做。
- 数据库里有这个对象,其属性改变了,就发送SQL更新数据库
- 数据库没有这个对象,则保存这个对象到数据库。
我想这样做的目的就是保证对象的原子性,不可能别人已经动过数据库了,你还拿一个脏对象来操作。大家可以修改上面的代码测试一下。
那么ISession.SaveOrUpdateCopy()方法在哪里使用呢?
在Web程序中应该没什么用处,因为我们常常使用session-per-request策略,请求之后Session就关闭了也没什么用了。但是在WPF程序中,经常在几个Session中操作对象,操作不慎,会出现各种各样的异常。比如我们如何把这个对象从一个Session中附加到另外一个Session中持久化使用呢。
相关文章
- Nginx-初识篇
- 从零开始实现lmax-Disruptor队列(五)Disruptor DSL风格API原理解析
- 【经典算法】第七回:堆排序
- 响应式编程WebFlux-SpringBoot(5)
- 记录用C#写折半查找算法实现
- 【Avalonia】【跨平台】关于Prism项目模块化在Linux下路径问题
- 《软技能-代码之外的生存指南》读书笔记
- C# 实现你自己的异步方法
- 07-Feign远程调用
- 分布式事务TCC
- Spring Cloud体系中Eureka闭源,作用Consul做注册中心到底爽不爽?
- 高企必备项目—SSM框架项目CRM客户管理系统
- 多态详解
- Static、Final关键字详解
- 代理设计模式还不会?2分钟搞定
- instanceof和类型转换
- 未能加载文件或程序集“XXX.dll”或它的某个依赖项的解决方法
- ReentrantLock 公平锁源码 第2篇
- 2022-7-7学习日记
- 设计模式 01 单例模式