我正在尝试使用NHibernate保存映射的实体,但是我对数据库的插入失败,因为基础表有一个不允许空值的列而且IS未映射到我的域对象中。它未被映射的原因是因为所讨论的列支持遗留应用程序并且与我的应用程序无关 - 所以我不希望使用遗留属性污染我的实体。
我知道我可以在课堂上使用私人场地 - 但这对我来说仍然很难受。我read我可以使用NHibernate拦截器并覆盖OnSave()方法,在我的实体保存之前添加到新列中。这很难说,因为我无法弄清楚如何将Nhibernate.type.IType的实例添加到拦截器的OnSave的types参数中。
我的实体大致如下:
public class Client
{
public virtual int Id { get; set; }
public virtual int ParentId { get; set; }
public virtual string Name { get; set; }
public virtual string Phone { get; set; }
public virtual string Email { get; set; }
public virtual string Url { get; set; }
}
我的拦截器
public class ClientInterceptor : EmptyInterceptor
{
public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types)
{
if (entity is Client)
{
/*
manually add the COM_HOLD column to the Client entity
*/
List<string> pn_list = propertyNames.ToList();
pn_list.Add("COM_HOLD");
propertyNames = pn_list.ToArray();
List<Object> _state = state.ToList();
_state.Add(false);
state = _state.ToArray();
//somehow add an IType to types param ??
}
return base.OnSave(entity, id, state, propertyNames, types);
}
}
有没有人对如何正确地做到这一点有任何想法?
答案 0 :(得分:1)
就我个人而言,我不会这么复杂。我会添加私有属性并为其分配一个默认值 - 完成。您还可以考虑数据库中的默认值,然后您不需要执行任何其他操作。
private virtual bool COM_HOLD
{
get { return false; }
set { /* make NH happy */ }
}
在为此编写拦截器之前,我会考虑编写一个数据库触发器。因为使用Interceptor,您正在“污染”您的数据访问层。 可以使其不稳定,而可能有奇怪的问题。
答案 1 :(得分:1)
我不能肯定地说,因为我从来没有真正这样做过(比如Stefan,我也更喜欢只添加一个私人财产),但是你可以在NHibernate.Type.BooleanType
添加types
吗?数组?
List<IType> typeList = types.ToList();
typeList.Add(new BooleanType());
types = typesList.ToArray();
修改强>
是的,看起来你是对的;类型有internal
构造函数。我做了一些挖掘,发现了TypeFactory
:
应用程序应使用静态 方法和常量 NHibernate.NHibernateUtil如果 默认的IType足够好了。例如,TypeFactory应该只 当String需要长度为300而不是255时使用。此时 NHibernate.String不能让你得到正确的IType。而是使用TypeFactory.GetString(300)并保持一个 保存对IType的引用的局部变量。
所以看起来你想要的是NHibernateUtil
:
提供对全方位的访问权限 NHibernate内置类型。 ITYPE 实例可用于绑定值 查询参数。也是一家工厂 对于新的Blob和Clobs。
typeList.Add(NHibernateUtil.Boolean);