【问题标题】:NHibernate : No update with composite keyNHibernate:没有使用复合键更新
【发布时间】:2015-06-17 10:03:11
【问题描述】:

我有一个使用 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)。有什么想法吗?

【问题讨论】:

  • 这里非常重要的是:“Session.SaveOrUpdate(entity)”保留任何东西。它只是更改会话中的数据(如果之前已分离)...请确保您已调用 Session.Flush()
  • @RadimKöhler:谢谢。正如您可能已经看到的,我添加了这个,但它只是好一点。还有其他想法吗?
  • Seyos,您很可能不喜欢我的回答,但我认为这是我可以分享的最佳建议。希望对您有所帮助...

标签: c# nhibernate fluent-nhibernate


【解决方案1】:

我。 PERSISTING,正在执行sql写入命令

正如 cmets 中所讨论的,我们需要做的第一件事是使用 ISession.Flush()

扩展我们的代码

9.6. Flush

(有些引用)

...
除非您明确 Flush(),否则绝对不能保证 Session 何时执行 ADO.NET 调用,只能保证它们的执行顺序。 ...

正如这里所讨论的

How to change default FlushMode to Commit in C#?

我们可以在会话创建期间分配默认的刷新模式

var session = SessionFactory.OpenSession();
session.FlushMode = FlushMode.Commit;

并确保一旦提交事务就会调用它或明确调用它anytime我们需要

Session.SaveOrUpdate(entity);
Session.Flush();

二。键/ID 更改 已持久化,而非临时实体

这是设计使然,意图是不可能的。因为 DB Key,C# 运行时实体Id 是一个指向实例的数据层 指针。我们不应该使用这些,我们不应该尝试去思考它们

我们的实体应该只使用引用来管理:

var entity = ...;
entity.ContractType = someContractType;
entity.CreditorCountry = defaultCountry;
...

这样我们在 Flush() 上分配 db Keys,表示为 Ids...,而不提及它们。

这也是为什么我们不应该考虑改变它们的能力。

我们能做的最好的 - 就是不使用复合键 - 并使用

Surrogate Key

数据库中的代理键是建模世界中的实体或数据库中的对象的唯一标识符。代理键不是从应用程序数据派生的,与从应用程序数据派生的自然(或业务)键不同。

使用 SQL Server 很容易引入带有 IDENTITY(1,1) 的新列...只需使用 ALTER TABLE TheID INT NOT NULL IDENTITY(1,1) ... 就可以了

将所有复合部件重新映射到属性(.Map().References()),然后您可以更改任何您想要的内容

我可以理解这不是理想的答案,但我强烈建议至少考虑一下。简单来说,

密钥只能生成一次。然后永远保持不变......或与其行/实例一起删除

【讨论】:

  • Sig 我就知道会变成这样……啊!
  • 希望有一个更好的.. 享受强大的 NHibernate,先生!这是一个了不起的工具;)
  • 老实说,我不喜欢它。在大多数情况下它是有帮助的,但仅仅因为 5% 的情况,我更喜欢使用其他东西。只是这个项目是我用的老项目了。
【解决方案2】:

在将更改写入数据库之前,您必须刷新或提交会话。

也看看这个:

【讨论】:

  • 谢谢。我这样做了,它好一点,因为我可以更新任何值,除了键值(CreditorName 和 CreditorIBAN)。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
相关资源
最近更新 更多