假设我有一个用户实体,并且它具有不可为空的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
,只有它的视图。该属性仅用于登录过程,可以在重置密码功能中更新,其中生成新密码并将其发送到相关用户的电子邮件。
答案 0 :(得分:2)
我看到了实现这个目标的两种可能性
在更新前获取实体并明确更新
// 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();
}
}
针对不同的行为使用不同的类
您可以为同一个实体声明不同的类。用于创建或密码重置的一个类,其中包含password属性。还有一个类,用于不需要password属性的简单更新。 FluentNhibernate允许您为同一个表映射不同的类。但是你需要更多的努力来映射,或者更确切地说是AutoMappingOverrides。