在具有ICollection<>类型属性的Class上按代码映射

时间:2013-05-12 01:58:50

标签: nhibernate nhibernate-mapping

我想通过代码使用NHibernate映射来映射具有类型ICollection<>的属性的类。以下代码有效。但是我不喜欢Person中的额外CarSet属性来使映射工作。

 public class PersonSet
    {        
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual ICollection<CarSet> Cars { get; set; }
    }

    public class CarSet
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual PersonSet Person { get; set; }
    }


    public class PersonSetMap : ClassMapping<PersonSet>
    {
        public PersonSetMap()
        {
            Id(x => x.Id, m=>m.Generator(Generators.Identity));
            Property(x=>x.Name);
            Set(x => x.Cars, c =>
                {
                    c.Key(k =>
                        {
                            k.Column("PersonId");
                        });
                     c.Cascade(Cascade.Persist);
                    c.Lazy(CollectionLazy.NoLazy);
                }, r =>
                    {
                        r.OneToMany();
                    }
                );
        }
    }

    public class CarSetMap : ClassMapping<CarSet>
    {
        public CarSetMap()
        {
            Id(x => x.Id, m => m.Generator(Generators.Identity));
            Property(x => x.Name);
            ManyToOne(x => x.Person, m =>
            {
                m.Column("PersonId");
                m.Cascade(Cascade.None);
                m.NotNullable(true);
            });

        }
    }

      public void Save(){

       using (var session = Cfg.Session)
            using (var tx = session.BeginTransaction())
            {
               PersonSet John = new PersonSet { Name = PersonName.John };
               John.Cars = new List<CarSet> { 
                new CarSet { Name = CarnName.BMW,Person = John},
                  new CarSet { Name = CarnName.BM,Person = John }};
                session.Save(entity);
                tx.Commit();
            }

    }

上面的代码生成以下SQL脚本:

  create table PersonSet (
      Id INT IDENTITY NOT NULL,
     Name NVARCHAR(255) null,
     primary key (Id)
  )

  create table CarSet (
      Id INT IDENTITY NOT NULL,
     Name NVARCHAR(255) null,
     PersonId INT not null,
     primary key (id)
  )

  alter table CarSet
      add constraint FKF967D6489A220265
      foreign key (PersonId)
      references PersonSet

我想要的是生成如下所示差异的SQL脚本,并保持其余部分相同:

 create table CarSet (     
     Name NVARCHAR(255) null,
     PersonId INT not null,

  )

理想情况下,我想要这样的CarSet

public class CarSet
{
    public virtual int PersonId { get; set; }
    public virtual string Name { get; set; }

}

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

将Cars映射为ComponentCollection

class Person
{

    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Car> Cars { get; set; }
}

class Car
{
    public virtual Person Owner { get; set; }
    public virtual string Name { get; set; }
}

public class PersonMap : ClassMapping<Person>
{
    public PersonMap()
    {
        Id(x => x.Id, m => m.Generator(Generators.Identity));
        Property(x => x.Name);
        Set(x => x.Cars, c =>
        {
            c.Key(k => k.Column("PersonId"));
            c.Cascade(NHibernate.Mapping.ByCode.Cascade.Persist);
            c.Lazy(CollectionLazy.NoLazy);
        }, r =>
        {
            r.Component(c =>
            {
                c.Parent(x => x.Owner);
                c.Property(x => x.Name);
            });
        });
    }
}

答案 1 :(得分:0)

您的理想解决方案是不可能的。要使用没有自己的ID列的CarSet表,它必须是一个组件,但组件集不能有可为空的列。如果您可以将Name标记为非空,则可以调整Firo发布的解决方案。

如果不行,您至少可以解决第一个删除Person属性的请求。只需删除属性并将集合映射中的键列标记为不可为空。 CarSet仍然是一个实体(因此拥有自己的ID),但您不需要在代码中引用PersonSet

顺便问一下,为什么你的课程后缀为Set?只需将它们命名为PersonCar会更好,因为它们只代表一个人或汽车,而不是它们的集合。