【问题标题】:NHibernate: How to know if, on Flush() SQL will be sent?NHibernate:如何知道是否会在 Flush() 上发送 SQL?
【发布时间】:2014-07-02 12:57:42
【问题描述】:

我对 NHibernate 的 IsDirty() 方法有点困惑。

从我的数据库中获取一个(非常大的)复杂对象后,NHibernate 的 ISession.IsDirty() 直接给出“真”。

IFacadeDAL fd = new FacadeDAL();
// Session's not dirty

IProject proj = fd.GetByID<IProject, string>("123611-3640");
// Session is dirty

但是,如果我像这样调用 Commit():

using (ITransaction trans = Facade.Session.Transaction)
{
    trans.Begin();
    Facade.Session.Save(entity);
    trans.Commit();
    return true;
}

这会导致没有 sql(“exec sp_reset_connection”除外)。

我已经读到,由于“映射选择”,您可以在会话中获得“幽灵”(导致会话说它很脏),但它不会也尝试更新一些东西吗?此外,如果这是由于例如通过将 sql 位“转换”为 c# bool,我认为我无法更改它...(不过,不知道这是否会导致出现鬼魂)。

更新 2: 这里涉及到几个(sql server)视图表。这是(非常)简化的类:

public class Project : IProject
{
    private string id;
    private List<IPlantItem> plantItems;

    public Project() { }

    public virtual string ID
    {
        get { return id; }
    }

    public virtual IEnumerable<IPlantItem> PlantItems
    {
        get { return plantItems; }
    }
}

'PlantItem 正在存储在表中。所以我希望当我更改 PlantItem 中的任何内容时,IsDirty 应该更改为“true”。

我的问题是:有没有办法检查当时的会话是否会在 flush() 上(或者在我的情况下在 commit() 上)会生成实际的 sql 语句?如果没有:是否有另一种方式(手动)存储某种会话快照以与当前会话进行比较?

更新 1:我还真的应该提到这些方面:

  1. 我的 FlushMode 设置为“无”。
  2. 'IProject'-object 本身的底层数据基于 sql-view,因此映射集中的大多数属性设置为 update="false"
  3. 当我实际更改对象中的某些内容并使用相同的保存方法时,正在发送 sql 更新语句(因此一切都已提交)

【问题讨论】:

  • 只是为了确定:您的FlushMode 是否设置为NONE?如果是的话:为什么你不在trans.Commit() 之前打电话给session.Flush()? None 意味着永远不会调用 Flush。从来没有,也没有提交。
  • @Radim:Thnks Radim,但在这种情况下我使用 nh ITransaction,所以根据这个:nhforge.org/doc/nh/en/index.html#manipulatingdata-endingsession,我不必这样做。此外,所有其他功能都可以正常工作(提交更改和其他内容)。
  • 你能不能有一个幽灵映射,让会话认为它很脏,但是因为你把它映射为update="false",所以不会发送更新?
  • 阻止对视图的任何更新的肮脏技巧(我怀疑您有鬼)是将&lt;class name="Foo" table="foo_table" mutable="false"&gt; 添加到您的类映射中
  • 为什么将 mutable 设置为 false 是一个肮脏的 hack?我建议查看捉鬼敢死队测试并将其包含在您的测试服中。 joseoncode.com/2010/02/05/nhibernate-ghostbuster-version-1-1

标签: session nhibernate flush dirty-data


【解决方案1】:

根据我的经验,鬼可能是由于数据库是nullable int 而映射是普通的int

当实体被水合时,nullable db int 被转换为zero,因此它现在是脏的。

另一种获取脏记录的方法是在 XML 映射中指定错误的类型,例如

public enum Sex
{
 Unspecified,
 Male,
 Female
}
...
public virtual Sex Sex { get; set; }

并在映射中指定一个 int。

 <property name="Sex" type="int"/>

请参阅此link to test your mappings,其中有更详细的说明。

【讨论】:

    【解决方案2】:

    如果您的某些实体是脏的 - 因此 ISession 是脏的 - 它们的属性和数据库之间存在不匹配。例如,假设您的表中有一个可以为空的列,但在您的代码中它被设置为非空(例如,一个 int)。 NHibernate 会认为它是脏的,因为它的当前值(如果是整数,则为 0)与来自 d​​b 的值(null)不同。在 Google 中查找“Ghost properties NHibernate”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-13
      • 1970-01-01
      • 2018-10-23
      • 2019-11-10
      • 2014-03-03
      • 2021-05-14
      • 2010-10-21
      • 2011-04-17
      相关资源
      最近更新 更多