gpt4 book ai didi

.net - 如何将 NHibernate 与 System.Tuple 等不可变类型一起使用?

转载 作者:行者123 更新时间:2023-12-04 05:40:23 29 4
gpt4 key购买 nike

我有一个使用 System.Tuple<int,string> 的复合映射看起来如下:

<composite-element
class="System.Tuple`2[[System.Int32, mscorlib],[System.String, mscorlib]], mscorlib">
<property name="Item1" column="DBColumn1"/>
<property name="Item2" column="DBColumn2"/>
</composite-element>

我试着弄乱 BytecodeProvider , IObjectsFactory , ReflectionOptimizer等等,但我无法让 NHibernate 正确加载我的元组(无论我做什么,NHibernate 都坚持先创建对象,然后再填充值)。

NHibernate 可以以某种方式强制正确加载和持久化不可变类型吗?

最佳答案

您是否尝试过 ICompositeUserType ?它将允许您为您的 Tuple<int, string> 定义这样的映射。属性:

<property name="MyProperty" type="MyNamespace.TupleIntStringType, MyAssembly">
<column name="Item1"/>
<column name="Item2"/>
</property>

自定义类型定义为:
public class TupleIntStringType : ICompositeUserType
{
public object GetPropertyValue(object component, int property)
{
var tuple = (Tuple<int, string>)component;
switch (property)
{
case 0:
return tuple.Item1;
case 1:
return tuple.Item2;
default:
throw new InvalidOperationException(String.Format("No property number {0} found", property));
}
}

public void SetPropertyValue(object component, int property, object value)
{
throw new InvalidOperationException("Immutable, SetPropertyValue is not allowed");
}

public new bool Equals(object x, object y)
{
if (ReferenceEquals(x, y)) return true;

if (x == null || y == null) return false;

return x.Equals(y);
}

public int GetHashCode(object x)
{
return x == null ? 0 : x.GetHashCode();
}

public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner)
{
var item1 = (int)PropertyTypes[0].NullSafeGet(dr, names[0], session, owner);
var item2 = (String)PropertyTypes[1].NullSafeGet(dr, names[1], session, owner);

return Tuple.Create(item1, item2);
}

public void NullSafeSet(IDbCommand cmd, object value, int index, bool[] settable, ISessionImplementor session)
{
if (value == null)
{
NHibernateUtil.Timestamp.NullSafeSet(cmd, null, index);
NHibernateUtil.TimeSpan.NullSafeSet(cmd, null, index + 1);
}
else
{
var tuple = (Tuple<int, String>)value;

PropertyTypes[0].NullSafeSet(cmd, tuple.Item1, index, session);
PropertyTypes[1].NullSafeSet(cmd, tuple.Item2, index + 1, session);
}
}

public object DeepCopy(object value)
{
var tuple = (Tuple<int, String>)value;
return Tuple.Create(tuple.Item1, tuple.Item2);
}

public object Disassemble(object value, ISessionImplementor session)
{
return DeepCopy(value);
}

public object Assemble(object cached, ISessionImplementor session, object owner)
{
return DeepCopy(cached);
}

public object Replace(object original, object target, ISessionImplementor session, object owner)
{
return DeepCopy(original);
}

public string[] PropertyNames { get { return new[] { "Item1", "Item2" }; } }
public IType[] PropertyTypes { get { return new IType[] { NHibernateUtil.Int32, NHibernateUtil.String }; } }
public Type ReturnedClass { get { return typeof(Tuple<int, string>); } }
public bool IsMutable { get { return false; } }
}

以下是几个例子:
Money object and NHibernate ICompositeUserType
Mapping Timestamp data using NHibernate's ICompositeUserType
Using NHibernate ICompositeUserType with a value type

您对 <composite-element> 的映射然后更改为(如 NHIbernate: How to map a bag with an ICompositeUserType 所示):
<element type="MyNamespace.TupleIntStringType, MyAssembly">
<column name="DBColumn1" />
<column name="DBColumn2" />
</element>

关于.net - 如何将 NHibernate 与 System.Tuple 等不可变类型一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11328026/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com