NHibernate 在拦截器中添加未映射的列

发布于 2024-07-19 03:02:20 字数 1542 浏览 3 评论 0原文

我正在尝试使用 NHibernate 保存映射实体,但我对数据库的插入失败,因为基础表有一列不允许为空并且未映射到我的域对象中。 它未映射的原因是因为相关列支持旧应用程序并且与我的应用程序无关 - 所以我不想用旧属性污染我的实体。

我知道我可以在班级中使用私有字段 - 但这对我来说仍然感觉很糟糕。 我读到我可以使用 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);
    }
}

有人对如何正确执行此操作有任何想法吗?

I'm trying to save a mapped entity using NHibernate but my insert to the database fails because the underlying table has a column that does not allow nulls and IS NOT mapped in my domain object. The reason it isn't mapped is because the column in question supports a legacy application and has no relevance to my application - so I'd like to not pollute my entity with the legacy property.

I know I could use a private field inside my class - but this still feels nasty to me. I've read that I can use an NHibernate interceptor and override the OnSave() method to add in the new column right before my entity is saved. This is proving difficult since I can't work out how to add an instance of Nhibernate.type.IType to the types parameter of my interceptor's OnSave.

My Entity roughly looks like this:

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; }
}

And my interceptor

 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);
    }
}

Does anyone have any ideas on how to do this properly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

偏爱你一生 2024-07-26 03:02:20

我不能肯定地说,因为我从来没有真正这样做过(像 Stefan 一样,我也更喜欢只添加一个私有属性),但是你可以只添加一个 NHibernate.Type.BooleanType类型数组?

List<IType> typeList = types.ToList();
typeList.Add(new BooleanType());
types = typesList.ToArray();

编辑

是的,看起来你是对的; 这些类型有一个内部构造函数。 我做了一些挖掘,发现了 TypeFactory:

应用程序应该使用静态
方法和常量
NHibernate.NHibernateUtil 如果
默认的 IType 就足够了。 例如,TypeFactory 应该只
当字符串需要长度为 300 而不是 255 时使用。此时
NHibernate.String 无法为您提供正确的 IType。 相反,使用 TypeFactory.GetString(300) 并保留
保存对 IType 的引用的局部变量。

所以看起来你想要的是 NHibernateUtil

提供对全系列的访问
NHibernate 内置类型。 类型
实例可用于绑定值
查询参数。 还有工厂
对于新的 Blob 和 Clob。

typeList.Add(NHibernateUtil.Boolean);

I can't say for sure since I've never actually done this (like Stefan, I also prefer to just add a private property), but can you just add a NHibernate.Type.BooleanType to the types array?

List<IType> typeList = types.ToList();
typeList.Add(new BooleanType());
types = typesList.ToArray();

EDIT

Yes, it looks like you are right; the types have an internal constructor. I did some digging and found TypeFactory:

Applications should use static
methods and constants on
NHibernate.NHibernateUtil if the
default IType is good enough. For example, the TypeFactory should only
be used when the String needs to have a length of 300 instead of 255. At this point
NHibernate.String does not get you thecorrect IType. Instead use TypeFactory.GetString(300) and keep a
local variable that holds a reference to the IType.

So it looks like what you want is NHibernateUtil:

Provides access to the full range of
NHibernate built-in types. IType
instances may be used to bind values
to query parameters. Also a factory
for new Blobs and Clobs.

typeList.Add(NHibernateUtil.Boolean);
无声情话 2024-07-26 03:02:20

就我个人而言,我不会做得这么复杂。 我将添加私有属性并为其分配默认值 - 完成。 您还可以考虑数据库中的默认值,然后您不需要执行任何其他操作。

private virtual bool COM_HOLD 
{ 
  get { return false; } 
  set { /* make NH happy */ } 
}

在为此编写拦截器之前,我会考虑编写一个数据库触发器。 因为使用拦截器你正在“污染”你的数据访问层。 它可能使其不稳定,并且您可能遇到奇怪的问题。

Personally I wouldn't do it so complicated. I would add the private property and assign it a default value - finished. You could also consider a default value in the database, then you don't need to do anything else.

private virtual bool COM_HOLD 
{ 
  get { return false; } 
  set { /* make NH happy */ } 
}

Before writing a interceptor for that I would consider to write a database trigger. Because with the Interceptor you are "polluting" your data access layer. It could make it unstable and you could have strange problems.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文