【问题标题】:Fluent Nhibernate: key-referencing an entity with a compositeIdFluent Nhibernate:键引用具有复合ID的实体
【发布时间】:2018-01-18 16:52:05
【问题描述】:

我在使用 Fluent Nhibernate 映射这些关系时遇到问题:

请求实体:

  • 身份证
  • 日期

学校实体:

  • 复合 id 由
    • 姓名
    • 请求
  • 财产

位置实体:

  • 复合 id 由
    • 存在(布尔值)
    • 学校(-> school_name 和 request_id 的外键)

基本上,这些关系代表了我向某所学校询问某个 Web api 服务的情况。我想保存请求(我在这里只放了日期,但我还有很多字段)以及为学校检索的信息。我还想将此信息与生成信息的请求绑定。 我也想像以前一样保存学校位置和绑定这个信息。

到目前为止我做了什么:

School.cs:

public class School
{
    public virtual string name {get; set;}
    public virtual Request request {get; set;}
    public virtual string property;
}

Request.cs:

public class Request
{
   public virtual int id {get; set;}
   public virtual DateTime date {get; set;}
}

Location.cs:

public class Location
{
    public virtual bool exist {get; set;}
    public virtual School school {get; set;}
    public virtual string province {get; set;}
}

SchoolMap.cs

public class SchoolMap : ClassMap<School>
{
    public SchoolMap() {
        CompositeId().KeyProperty(x => x.name, "name")
                     .KeyProperty(x => x.request, "request_id");
        Map(x => x.property);
    }
}

RequestMap.cs

public class Request : ClassMap<Request>
{
    public SchoolMap() {
        Id(x => x.id).GeneratedBy.Identity();
        Map(x => x.date);
    }
}

LocationMap.cs

public class LocationMap : ClassMap<Location>
{
    public LocationMap() {
        CompositeId().KeyProperty(x => x.exist)
                     .KeyReference(x => x.school, new string[] {"name", "request_id"});

        References<School>(x => x.school).Columns(new string [] {"name", "request_id"}).Cascade.All();
        Map(x => x.province);
    }
}

我还实现了从 AbstractRepository 继承的每个存储库。 “保存”方法是(以 SchoolRepository 为例)

public School saveSchool(School school)
{
    var transaction = openTransaction();
    session.saveOrUpdate(school);
    transaction.commit();
    return school;
}

这个方案行不通。 如果我创建并保存(按此顺序)一个请求,然后是引用该请求的一所学校,然后是引用学校的一个位置,我会收到“SqlParameter OutOfBound”异常。

我不知道如何映射这种关系。

在此先感谢大家。

【问题讨论】:

    标签: foreign-keys fluent-nhibernate composite-primary-key composite-id


    【解决方案1】:
    public class EntityC
    {
        private EntityA _EntityA;
        private EntityB _EntityB;
    
        public EntityC()
        {
            Id = new EntityCId();
        }
    
        public virtual EntityCId Id { get; protected set; }
    
        public virtual int EntityA_Id { get { return Id.EntityA_Id; } protected set { Id.EntityA_Id = value; } }
        public virtual EntityA EntityA { get { return _EntityA; } set { _EntityA = value; EntityA_Id = value == null ? 0 : value.Id.Id; } }
    
        public virtual int EntityB_Id { get { return Id.EntityB_Id; } protected set { Id.EntityB_Id = value; } }
        public virtual EntityB EntityB { get { return _EntityB; } set { _EntityB = value; EntityB_Id = value == null ? 0 : value.Id.Id; } }
    }
    
    public class EntityCMap : FluentNHibernate.Mapping.ClassMap<EntityC>
    {
        public EntityCMap()
        {
            CompositeId(t => t.Id).KeyProperty(t => t.Id).CustomType<int>()
                                  .KeyProperty(t => t.EntityA_Id).CustomType<int>()
                                  .KeyProperty(t => t.EntityB_Id).CustomType<int>();
    
            Map(t => t.EntityA_Id).Not.Insert().Not.Update();
            References(t => t.EntityA).Columns("EntityA_Id");
    
            Map(t => t.EntityB_Id).Not.Insert().Not.Update();
            References(t => t.EntityB).Columns("EntityA_Id", "EntityB_Id");
        }
    }
    public class EntityCId
    {
        public virtual int EntityA_Id { get; set; }
        public virtual int EntityB_Id { get; set; }
    
        public virtual int Id { get; set; }
    
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            var t = obj as EntityCId;
            if (t == null)
                return false;
            if (EntityA_Id == t.EntityA_Id && EntityB_Id == t.EntityB_Id && Id == t.Id)
                return true;
            return false;
        }
        public override int GetHashCode()
        {
            return (EntityA_Id + "|" + EntityB_Id + "|" + Id).GetHashCode();
        }
    }
    

    【讨论】:

      【解决方案2】:

      我试图展示一些复合的身份关系。

          public class EntityA
          {
              public EntityA()
              {
                  Id = new EntityAId();
              }
      
              public virtual EntityAId Id { get; protected set; }
          }
      
          public class EntityAMap : FluentNHibernate.Mapping.ClassMap<EntityA>
          {
              public EntityAMap()
              {
                  CompositeId(t => t.Id).KeyProperty(t => t.Id).CustomType<int>();
              }
          }
      
          public class EntityB
          {
              private EntityA _EntityA;
      
              public EntityB()
              {
                  Id = new EntityBId();
              }
      
              public virtual EntityBId Id { get; protected set; }
      
              public virtual int EntityA_Id { get { return Id.EntityA_Id; } protected set { Id.EntityA_Id = value; } }
              public virtual EntityA EntityA { get { return _EntityA; } set { _EntityA = value; EntityA_Id = value == null ? 0 : value.Id.Id; } }
          }
      
          public class EntityBMap : FluentNHibernate.Mapping.ClassMap<EntityB>
          {
              public EntityBMap()
              {
                  CompositeId(t => t.Id).KeyProperty(t => t.Id).CustomType<int>()
                                        .KeyProperty(t => t.EntityA_Id).CustomType<int>();
      
                  Map(t => t.EntityA_Id).Not.Insert().Not.Update();
                  References(t => t.EntityA).Columns("EntityA_Id");
              }
          }
      
          public class EntityAId
          {
              public virtual int Id { get; set; }
      
              public override bool Equals(object obj)
              {
                  if (obj == null)
                      return false;
                  var t = obj as EntityAId;
                  if (t == null)
                      return false;
                  if (Id == t.Id)
                      return true;
                  return false;
              }
              public override int GetHashCode()
              {
                  return (Id).GetHashCode();
              }
          }
      
          public class EntityBId
          {
              public virtual int EntityA_Id { get; set; }
              public virtual int Id { get; set; }
      
              public override bool Equals(object obj)
              {
                  if (obj == null)
                      return false;
                  var t = obj as EntityBId;
                  if (t == null)
                      return false;
                  if (EntityA_Id == t.EntityA_Id && Id == t.Id)
                      return true;
                  return false;
              }
              public override int GetHashCode()
              {
                  return (EntityA_Id + "|" + Id).GetHashCode();
              }
          }
      

      【讨论】:

      • 在您的情况下,EntityA 和 EntityB 都有一个仅由整数组成的主键。在我的情况下,我需要复合主键
      • EntityB 有两个 id 字段,表示有复合 id。其中之一是 EntityA_Id,它引用了 EntityA。如果您需要一个实体在复合 id 中至少有两个被引用的实体,那么请查看下一个答案
      猜你喜欢
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多