NHibernate:没有使用复合键的更新
NHibernate : No update with composite key
我有一个使用 Nhibernate 保存的对象。该对象使用复合键并声明如下:
CompositeId()
.KeyProperty(x => x.CreditorName)
.KeyProperty(x => x.CreditorIBAN)
.KeyReference(x => x.Config, "ProfileName");
Map(x => x.ID, "ID").ReadOnly();
Map(x => x.CreationDate, "CreationDate").Default(null);
Map(x => x.ContractReference, "ContractReference");
Map(x => x.CreditorBIC, "CreditorBIC");
References<C_ContractType>(x => x.ContractType, "ContractType_ID");
References<C_Country>(x => x.CreditorCountry, "CreditorCountry");
Table("Creditor");
Cache.ReadWrite();
我们可以毫无问题地继续保存,但是当我们尝试使用 Session.SaveOrUpdate(entity);
更新字段(无论是哪个字段)时,没有任何操作(没有更新)也没有错误消息。
我们错过了什么吗?感谢您的帮助!
-- 编辑--
我在更新方法之后添加了 Session.Flush()
,这样会好一些,因为我可以更新任何值,但键中的值(CreditorName 和 CreditorIBAN)除外。有什么想法吗?
在将更改写入数据库之前,您必须刷新或提交会话。
也看看这个:
- Flushing in NHibernate
- NHibernate Flush-- How it works?
我。 PERSISTING,执行sql写命令
正如评论中所讨论的,我们需要做的第一件事就是用 ISession.Flush()
扩展我们的代码
9.6. Flush
(有人引用)
...
Except when you explicity Flush(), there are absolutely no guarantees about when the Session executes the ADO.NET calls, only the order in which they are executed. ...
正如这里讨论的那样
How to change default FlushMode to Commit in C#?
我们可以在会话创建期间指定默认刷新模式
var session = SessionFactory.OpenSession();
session.FlushMode = FlushMode.Commit;
并确保在提交事务后调用它或显式调用它anytime
我们需要
Session.SaveOrUpdate(entity);
Session.Flush();
二. Key/Id 改变 已经持久化,而不是临时实体
这是设计使然,不可能的。因为DBKey
,C#运行时实体Id
是一个数据层指向实例的指针。我们不应该和这些一起工作,我们不应该试图去想它们
我们的实体应该只用引用来管理:
var entity = ...;
entity.ContractType = someContractType;
entity.CreditorCountry = defaultCountry;
...
通过这种方式,我们在 Flush() 上分配数据库密钥,表示为 ID...,而没有提及它们。
这也是为什么我们不应该考虑改变它们的能力。
我们能做的最好的事情 - 就是不使用复合键 - 而使用
Surrogate Key
A surrogate key in a database is a unique identifier for either an entity in the modeled world or an object in the database. The surrogate key is not derived from application data, unlike a natural (or business) key which is derived from application data.
使用 SQL 服务器很容易引入带有 IDENTITY(1,1) 的新列...只需使用 ALTER TABLE TheID INT NOT NULL IDENTITY(1,1)
... 那里有
将所有复合部件重新映射到属性(.Map()
或 .References()
),然后您可以根据需要进行任何更改
我能理解这不是想要的答案,但我强烈建议至少考虑一下。简单地说,
Key should be generated only once. Then left unchanged for ever ... or deleted with its row/instance
我有一个使用 Nhibernate 保存的对象。该对象使用复合键并声明如下:
CompositeId()
.KeyProperty(x => x.CreditorName)
.KeyProperty(x => x.CreditorIBAN)
.KeyReference(x => x.Config, "ProfileName");
Map(x => x.ID, "ID").ReadOnly();
Map(x => x.CreationDate, "CreationDate").Default(null);
Map(x => x.ContractReference, "ContractReference");
Map(x => x.CreditorBIC, "CreditorBIC");
References<C_ContractType>(x => x.ContractType, "ContractType_ID");
References<C_Country>(x => x.CreditorCountry, "CreditorCountry");
Table("Creditor");
Cache.ReadWrite();
我们可以毫无问题地继续保存,但是当我们尝试使用 Session.SaveOrUpdate(entity);
更新字段(无论是哪个字段)时,没有任何操作(没有更新)也没有错误消息。
我们错过了什么吗?感谢您的帮助!
-- 编辑--
我在更新方法之后添加了 Session.Flush()
,这样会好一些,因为我可以更新任何值,但键中的值(CreditorName 和 CreditorIBAN)除外。有什么想法吗?
在将更改写入数据库之前,您必须刷新或提交会话。
也看看这个:
- Flushing in NHibernate
- NHibernate Flush-- How it works?
我。 PERSISTING,执行sql写命令
正如评论中所讨论的,我们需要做的第一件事就是用 ISession.Flush()
9.6. Flush
(有人引用)
...
Except when you explicity Flush(), there are absolutely no guarantees about when the Session executes the ADO.NET calls, only the order in which they are executed. ...
正如这里讨论的那样
How to change default FlushMode to Commit in C#?
我们可以在会话创建期间指定默认刷新模式
var session = SessionFactory.OpenSession();
session.FlushMode = FlushMode.Commit;
并确保在提交事务后调用它或显式调用它anytime
我们需要
Session.SaveOrUpdate(entity);
Session.Flush();
二. Key/Id 改变 已经持久化,而不是临时实体
这是设计使然,不可能的。因为DBKey
,C#运行时实体Id
是一个数据层指向实例的指针。我们不应该和这些一起工作,我们不应该试图去想它们
我们的实体应该只用引用来管理:
var entity = ...;
entity.ContractType = someContractType;
entity.CreditorCountry = defaultCountry;
...
通过这种方式,我们在 Flush() 上分配数据库密钥,表示为 ID...,而没有提及它们。
这也是为什么我们不应该考虑改变它们的能力。
我们能做的最好的事情 - 就是不使用复合键 - 而使用
Surrogate Key
A surrogate key in a database is a unique identifier for either an entity in the modeled world or an object in the database. The surrogate key is not derived from application data, unlike a natural (or business) key which is derived from application data.
使用 SQL 服务器很容易引入带有 IDENTITY(1,1) 的新列...只需使用 ALTER TABLE TheID INT NOT NULL IDENTITY(1,1)
... 那里有
将所有复合部件重新映射到属性(.Map()
或 .References()
),然后您可以根据需要进行任何更改
我能理解这不是想要的答案,但我强烈建议至少考虑一下。简单地说,
Key should be generated only once. Then left unchanged for ever ... or deleted with its row/instance