NHibernate ICompositeUserType拆分字符串列

时间:2015-06-10 06:48:48

标签: c# nhibernate

我将为一个字符串属性实现一个ICompositeUserType,它被分成4列2000个字符(在传统的oracle数据库中,以避免CLOB / LONG字段)。 实现界面似乎是个好主意,但我无法理解SetPropertyValue方法。它不接受类型或字符串值。我需要它是可变的,所以我需要实现这个方法。

我可以使用非持久性属性来封装拆分并连接到x persitent属性,但我想要更透明的东西。

我发现了类似的问题,但没有像我预期的那样回应。

- 更新 -

我上传了一些代码来为问题添加上下文:

数据库:

...
Value VARCHAR2(2000 BYTE)
Value2 VARCHAR2(2000 BYTE)
Value3 VARCHAR2(2000 BYTE)
Value4 VARCHAR2(2000 BYTE)
Value5 VARCHAR2(2000 BYTE)
...

HBM:

<property name="Value" type="MyAssembly.NHibernateUtils.Types.MultiColumnJoinedUserType, MyAssembly">
  <column name="DFM_Value"/>
  <column name="DFM_Value2"/>
  <column name="DFM_Value3"/>
  <column name="DFM_Value4"/>
  <column name="DFM_Value5"/>
</property>    

CLASS:

    public virtual string Value { get; set; }

MultiColumnJoinedUserType:

    /// <summary>
    /// Set the value of a property
    /// </summary>
    /// <param name="component">an instance of class mapped by this "type"</param>
    /// <param name="property"></param>
    /// <param name="value">the value to set</param>
    public void SetPropertyValue(object component, int property, object value) { ... }

在我的班级中,方法的组件字段是一个字符串,因此在不更改引用的情况下无法更改其值,因为字符串作为值而不是作为我需要的引用传递。

3 个答案:

答案 0 :(得分:1)

ICompositeUserType通常用于.Net中有多个属性(例如&#34;组件&#34;)。这里有Money课程的示例:http://geekswithblogs.net/opiesblog/archive/2006/08/05/87218.aspx

由于.Net中只有一个简单值,因此您应该实现IUserType,这样您仍然可以在数据库中使用多个列。

答案 1 :(得分:0)

我在这个问题上花了几个小时尝试了各种解决方案:

  • 在ICompositeUserType
  • 中使用字符串[]而不是字符串
  • 使用IUserType而不是ICompositeUserType

两者都在Oracle中工作,但在SQL中(我需要兼容性),空值被设置为默认的null。

log4net中的NHibernate跟踪:

INSERT INTO VALUETABLE (HDF_Value1, HDF_Value2, HDF_Value3, HDF_Value4, HDF_Value5) VALUES (@p1, @p2, @p3, @p4, @p5); select SCOPE_IDENTITY(); @p1 = NULL [Type: String (4000)], @p2 = NULL [Type: String (4000)], @p3 = NULL [Type: String (4000)], @p4 = NULL [Type: String (4000)], @p5 = NULL [Type: String (4000)]

但是在SQLProfiler中:

exec sp_executesql N'INSERT INTO VALUETABLE (HDF_Value1, HDF_Value2, HDF_Value3, HDF_Value4, HDF_Value5) VALUES (@p1, @p2, @p3, @p4, @p5); select SCOPE_IDENTITY()',N'@p1 nvarchar(4000),@p2 nvarchar(4000),@p3 nvarchar(4000),@p4 nvarchar(4000),@p5 nvarchar(4000)',@p1=default,@p2=default,@p3=default,@p4=default,@p5=default

我在nullsafeset上尝试过各种代码(使用DBNull,string.NullSafeSet,...),但对我来说没有任何作用。我不能浪费更多时间,最后我实施了最简单的解决方案,5&#34;隐藏&#34;映射对象上的属性和&#34;虚拟&#34;分割和连接值的属性,它不是非常透明但它按预期工作:

    public virtual string _Value1 { get; set; }
    public virtual string _Value2 { get; set; }
    public virtual string _Value3 { get; set; }
    public virtual string _Value4 { get; set; }
    public virtual string _Value5 { get; set; }

    public virtual string Value
    {
        get
        {
            // JOIN VALUES FROM 5 _Value properties
        }
        set
        {
            // SPLIT VALUE INTO 5 _Value properties
        }
    }

这一刻对我来说足够了。

答案 2 :(得分:0)

字符串不可变。您可以放心地忽略SetPropertyValue。我在我的不可变用户类型中实现了GetPropertyValue,我认为它被调用。

    public bool IsMutable
    {
        get { return false; }
    }

    public void SetPropertyValue(object component, int property, object value)
    {
      throw new NotSupportedException("Something goes wrong here");
    }


    public object GetPropertyValue(object component, int property)
    {
      var stringComponent = (string)component;
      maxLengthToRead = Math.Min(2000, stringComponent.Length - property * 2000);
      if (maxLengthToRead <= 0) return string.Empty;

      return stringComponent.Substring(property * 2000, maxLengthToRead);
    }