防止与NHibernate / FluentNHibernate的多对多关系的级联更新,

时间:2011-04-19 13:34:55

标签: c# .net nhibernate fluent-nhibernate nhibernate-cascade

我在User类和Place类之间有一个简单的多对多关系。此关系由用户的“邻居”属性

表示
public class User
{
  public virtual IList<UserPlace> Neighbourhood { get; set; }
}

UserPlace类只是一个组件,它将一条信息添加到用户和地点之间的关系中:

public class UserPlace
{
  public virtual User User { get; set; }
  public virtual Place Place { get; set; }
  public virtual bool IsDefault { get; set; }
}

关系映射如下:

public class UserMappings : ClassMap<User>
{
  //... other mappings

  HasMany(x => x.NeighbourHood)
            .Component(c =>
                           {
                               c.Map(x => x.IsDefault);
                               c.References(x => x.Place).Cascade.None();
                           }
            ).Not.LazyLoad().Cascade.SaveUpdate();
}

创建用户时,会从数据库加载一些位置并添加到用户,其中一个位置设置为默认。当用户被持久化时,关联的UserPlace实体也会被持久化。

我遇到的问题是每个与UserPlace关联的 Place 实体也会更新。这不是理想的效果,我已经尝试通过将Cascade设置为None()来防止Cascade发生放置(双关语)......但是这并没有改变任何东西。

我只是通过指定不应更新Place上的每个属性([PropertyName] .Not.Updated())来设法停止此更新。这有效,但它不是解决方案。

有没有人对如何防止这种情况发生任何想法?

编辑:Place实体映射也指定了DynamicUpdate() - 因此在保存用户时实体不应该更改。

PS!我不认为它对这种情况有所影响(但我可能错了!),但也要考虑这一点: Place 实体是在NHibernate之外加载的(使用ADO.NET和存储过程,因为我无法用NHibernate进行一些地理空间查询,然后通过在每个实体上调用Session.Update()来附加到会话。

1 个答案:

答案 0 :(得分:1)

这不是一个级联问题。 NH会更新地点,因为您会在每个地方拨打session.Update。你在PS中写的内容与问题完全相关。

当您在分离的实体上调用update时,NH无法知道实体的状态是否实际发生了变化。为了避免在更新之前查询数据(两次数据库往返),它会盲目地更新数据。

为避免这种情况:

  • 设置select-before-update(SelectBeforeUpdate精通)
  • 使用session.Merge(place)。它还会在更新之前执行查询。请注意,它具有需要使用的返回值。
  • 使用session.Load(place.Id)创建相关地点的代理并进行分配(请注意,NH在访问代理的属性时会再次加载该地点)
  • 使用session.Lock(place, LockMode.None)将对象放入会话中。
  • 使用NH查询检索地方。