托塔雨天王 2023-01-08 18:18 采纳率: 100%
浏览 55
已结题

NHibernate

NHibernate.Mapping.Attributes如何实现复合主键的映射?

有一个数据表,主键是两列组成的复合主键,根据NHibernate关于复合组件的文档,需要将所有复合主键构成一个主键类,然后使用xml文件映射,这样才能用ISessionFactory.Session.Get(object obj)方法获取实体对象,但是我现在想用NHibernate.Mapping.Attributes库,利用C#的Attribute修饰我的主键类和目标类,应该怎么做?我的类已经写好了,主要是不知道两个类的Attribute应该怎么处理。

  • 写回答

1条回答 默认 最新

  • m0_54204465 2023-01-08 20:54
    关注

    使用 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; }
    
    // 其他属性}
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 1月16日
  • 已采纳回答 1月8日
  • 创建了问题 1月8日

悬赏问题

  • ¥15 腾讯云如何建立同一个项目中物模型之间的联系
  • ¥30 VMware 云桌面水印如何添加
  • ¥15 用ns3仿真出5G核心网网元
  • ¥15 matlab答疑 关于海上风电的爬坡事件检测
  • ¥88 python部署量化回测异常问题
  • ¥30 酬劳2w元求合作写文章
  • ¥15 在现有系统基础上增加功能
  • ¥15 远程桌面文档内容复制粘贴,格式会变化
  • ¥15 这种微信登录授权 谁可以做啊
  • ¥15 请问我该如何添加自己的数据去运行蚁群算法代码