在NHibernate更新时跳过属性

时间:2017-03-09 14:59:58

标签: c# asp.net-mvc nhibernate fluent-nhibernate automapper

假设我有一个用户实体,并且它具有不可为空的Password属性

Map((x) => x.Password).Column("PASSWORD").Not.Nullable();

在创建操作中,我手动设置Password值,因为它是生成的哈希值。它永远不会进入视图。

在更新中,我尝试保存它,但我没有Password值。我收到了Password有问题的错误:

  

PropertyValueException:not-null属性引用空值或瞬态值

这是我的更新方法:

public bool Update(UserViewModel input)
{
    if (!IsValid(input))
        return false;

    var user = Mapper.Map<User>(input);

    this.UserRepository.Update(user); // <- this is a wrapper for NH's Session.Update()

    return true;
}

如何告诉NHibernate忽略更新中的属性?

注意:这与this question不同。

更新

以下是我如何使用它:Password属性永远不会进入任何视图。即使在登录操作中,我也有一个通用的LoginViewModel,只有它的视图。该属性仅用于登录过程,可以在重置密码功能中更新,其中生成新密码并将其发送到相关用户的电子邮件。

1 个答案:

答案 0 :(得分:2)

我看到了实现这个目标的两种可能性

  1. 在更新前获取实体并明确更新

    // use 'Get()' because it uses the NHibernate cache
    // if you already loaded the entity, it won't query the db and read it from the cache
    var user = this.UserRepository.Get(input.Id); 
    user.PropertyToUpdate = ...;
    this.UserRepository.Update(user);
    

    除此之外,您还可以使用Dynamic-Update但是这只适用于绑定到Session的实体。 NHibernate将只更新已更改的属性,而不是更新实体时的所有属性。否则NHibernate无法知道哪些属性已更改并将更新所有属性。只有从NHibernate获得实体时,DynamicUpdate才有效。然后将实体绑定到Context,NHibernate可以跟踪更改。

    如果您的所有实体都是自动映射的,您可以使用ClassConvention将DynamicUpdate设置为您的所有实体(或只过滤您想要的实体):

    public class ClassConvention : IClassConvention
    {
        public void Apply(IClassInstance instance)
        {
            instance.DynamicUpdate();
        }
    }
    

    作为另一个选项,您可以使用显式映射覆盖:

    public class UserOverride : IAutoMappingOverride<User>
    {
        public void Override(AutoMapping<User> mapping)
        {
            mapping.DynamicUpdate();
        }
    }
    
  2. 针对不同的行为使用不同的类

    您可以为同一个实体声明不同的类。用于创建或密码重置的一个类,其中包含password属性。还有一个类,用于不需要password属性的简单更新。 FluentNhibernate允许您为同一个表映射不同的类。但是你需要更多的努力来映射,或者更确切地说是AutoMappingOverrides。