Castle ActiveProject从FindAllByProperty检索过时的数据

时间:2018-11-09 03:20:25

标签: c# .net activerecord nhibernate castle-activerecord

我有一个较旧的WinForms 4.x应用程序,该应用程序在NHibernate 3.1.0.4000(不是最新版本,但是当前版本)上使用Castle.ActiveRecord 3.0.0 RC(我认为是最新的可用版本)。那个时候。)

我注意到一种形式内的数据不一致现象。它会在表单的整个生命周期内创建一个TransactionScope,直到最后才提交。它获取对象列表并为其提供一些编辑UI。其中之一是IsPrimary布尔属性的复选框。

只有一个对象应该具有IsPrimary == true,因此,当您选中复选框时,它确实具有:

var others = MyData.FindAllByProperty("IsPrimary", true)
        .Where(x => x.Name != current.Name).ToList();
foreach (var data in others)
{
    data.IsPrimary = false;
    data.Save();
}
current.IsPrimary = true;
current.Save();

(这可能可以更有效地完成,但是暂时忽略它。current是选中其复选框的对象。它们确实都有唯一的名称。)

这在大多数情况下都可以正常工作,但是如果您打开窗口,请在其他项目上打勾(这样就可以完成上述操作,并将上一个项目正确设置为false),然后在不关闭窗口的情况下尝试再次勾选第一项,最后得到两个对象集IsPrimary

问题似乎是FindAllByProperty正在返回表单事务之外的原始对象状态,而忽略了任何更改。

如果我用以下代码替换通话:

var others = MyData.FindAll().Where(x => x.IsPrimary)
        .Where(x => x.Name != current.Name).ToList();

然后它返回正确的结果(包括在表单事务中进行的更改)。

这是一个已知的错误吗?除了使用FindAll()以外,还有其他解决方法吗?


编辑:FWIW,使用显式条件具有相同的结果(它返回陈旧数据,而不是正确数据):

var criteria = DetachedCriteria.For(typeof(MyData))
    .SetResultTransformer(CriteriaSpecification.DistinctRootEntity)
    .Add(Restrictions.Eq("IsPrimary", true))
    .Add(Restrictions.Not(Restrictions.IdEq(current.Id)));
var others = MyData.FindAll(criteria);
// still stale

1 个答案:

答案 0 :(得分:0)

这是一起玩三件事:

  • 在不提交数据的情况下,数据库内部不会更改。
  • 在可能的情况下,nhibernate将strictins转换为SQL,并且数据库服务器运行检查。仅在可能的情况下。
  • 会话具有一个机会,如果返回的记录(主)键已经在该机会中,它将忽略该记录(值),而仅重用Cache中的对象。

这意味着Restrictions.Eq(“ IsPrimary”,true)或Where(x => x.IsPrimary)将(我认为)将在数据库服务器中运行,并且永远不会看到仅在应用程序中更改过的任何数据(aka。没有提交,又称瞬态数据,又称脏数据/对象)。这意味着,如果您的应用程序/会话/聊天中的一个对象中有多个对象具有IsPrimary = true,但您在数据库中仍然设置了IsPrimary = false,则设置为IsPrimary = false的对象列表就是最麻烦的列表。

您要么必须执行以下操作之一,但以自己的方式都不好:

  • 不受限制地加载所有对象
  • 或手动扫描会话以查找所有瞬态/脏物体
  • 或在每次更改IsPrimary后提交

如果可能的话,我建议您从表/类中的布尔字段切换到另一表/类中仅具有一个条目的数据对象类型的引用字段,并在其中存储主要对象其他表/类。如果两个会话/用户尝试同时创建一个主数据库(最好再创建两个主数据库:D),它将自动只允许一个主数据库并且会导致并发。

也许您的数据结构已经对您的数据类具有一种父级/上级类,并且应该知道IT是主要的。

问候 朱伊·朱卡