使用 NHibernate.Mapping.Attributes 库可以使用特性来映射复合主键类和目标类。
首先,你需要在复合主键类上使用 [CompositeId] 特性,然后在每个复合主键的属性上使用 [KeyProperty] 特性标注。
接下来,在目标类上使用 [Class] 特性,并在目标类中的复合主键类型的属性上使用 [Id] 特性。
这是一个示例:
[CompositeId]
public class CompositeKey
{
[KeyProperty]
public int Id1 { get; set; }
[KeyProperty]
public int Id2 { get; set; }
}
[Class]
public class TargetClass
{
[Id]
public CompositeKey CompositeKey { get; set; }
// other properties and methods
}
然后你就可以使用 ISession.Get(object id) 方法来获取目标类的实例,其中 id 参数是复合主键类的实例。
using (var session = sessionFactory.OpenSession())
{
var compositeKey = new CompositeKey { Id1 = 1, Id2 = 2 };
var target = session.Get<TargetClass>(compositeKey);
}
在使用 NHibernate.Mapping.Attributes 库时,如果在实体类上使用了 [CompositeId] 特性,那么这个实体类必须要继承自 ICompositeUserType 接口,并实现其中的方法。如果你的实体类没有继承自这个接口,会提示 [CompositeId] 不能是 [Class] 的特性。可以尝试将你的实体类改为继承自 ICompositeUserType 接口,然后再次尝试使用 [CompositeId] 特性进行复合主键映射。
在继承自 ICompositeUserType 接口时,还需要注意几点:
在实现 ICompositeUserType.GetPropertyNames() 方法时,需要返回复合主键中所有属性的名称。
在实现 ICompositeUserType.GetPropertyTypes() 方法时,需要返回复合主键中所有属性的类型。
在实现 ICompositeUserType.NullSafeSet() 和 ICompositeUserType.NullSafeGet() 方法时,需要注意将复合主键的值转换为相应的数据库类型。
这些方法的具体实现可以参考下面的示例代码:
public class CompositeKey : ICompositeUserType
{
public string[] PropertyNames => new[] { "Id1", "Id2" };
public System.Type[] PropertyTypes => new[] { typeof(int), typeof(string) };
public object GetPropertyValue(object component, int property)
{
var key = (CompositeKey)component;
return property == 0 ? key.Id1 : key.Id2;
}
public void SetPropertyValue(object component, int property, object value)
{
var key = (CompositeKey)component;
if (property == 0)
{
key.Id1 = (int)value;
}
else
{
key.Id2 = (string)value;
}
}
public new bool Equals(object x, object y)
{
if (ReferenceEquals(x, y))
{
return true;
}
if (x == null || y == null)
{
return false;
}
var xKey = (CompositeKey)x;
var yKey = (CompositeKey)y;
return xKey.Id1 == yKey.Id1 && xKey.Id2 == yKey.Id2;
}
public int GetHashCode(object x)
{
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
var id1 = (int)NHibernateUtil.Int32.NullSafeGet(rs, names[0]);
var id2 = (string)NHibernateUtil.String.NullSafeGet(rs,names[1]);return new CompositeKey { Id1 = id1, Id2 = id2 };
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
var key = (CompositeKey)value;
NHibernateUtil.Int32.NullSafeSet(cmd, key.Id1, index);
NHibernateUtil.String.NullSafeSet(cmd, key.Id2, index + 1);
}
public object DeepCopy(object value)
{
return value;
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return cached;
}
public object Disassemble(object value)
{
return value;
}
public System.Type ReturnedType => typeof(CompositeKey);
public bool IsMutable => false;}
在使用 [CompositeId] 特性进行复合主键映射时,还需要注意:
- 在实体类的复合主键属性上使用 [KeyProperty] 特性进行标注。
- 在实体类的复合主键属性上使用 [KeyType] 特性指定复合主键的类型。
示例代码如下:
[CompositeId]
[KeyType(typeof(CompositeKey))]
public class Entity
{
[KeyProperty]
public int Id1 { get; set; }
[KeyProperty]
public string Id2 { get; set; }
// 其他属性}