Nhibernate重复列

时间:2011-03-02 08:44:59

标签: c# .net nhibernate fluent-nhibernate nhibernate-mapping

我想映射以下简单实体:

public class AnimalsOwner
{
    public AnimalsOwner()
    {
        Cats = new List<Cat>();
        Dogs = new List<Dog>();
    }

    public virtual int Id { get; set; }

    public virtual IList<Cat> Cats { get; set; }

    public virtual IList<Dog> Dogs { get; set; }
}

public abstract class Animal
{
    public virtual int Id { get; set; }

    public virtual AnimalsOwner AnimalsOwner { get; set; }
}

public class Dog : Animal
{
    public virtual string DogsProperty { get; set; }
}

public class Cat : Animal
{
    public virtual string CatsProperty { get; set; }
}

使用以下映射:

public OwnerMapping()
    {
        this.Table("Owners");
        Id(x => x.Id)
            .GeneratedBy.Native();

        HasMany(x => x.Cats).AsBag().Cascade.SaveUpdate();
        HasMany(x => x.Dogs).AsBag().Cascade.SaveUpdate();
    }
}

public class AnimalMapping : ClassMap<Animal>
{
    public AnimalMapping()
    {
        this.Table("Animals");
        Id(x => x.Id).GeneratedBy.Native();

        References(x => x.AnimalsOwner).Not.Nullable();
    }
}

public class DogMap : SubclassMap<Dog>
{
    public DogMap()
    {
        this.Table("Dogs");
        this.KeyColumn("AnimalId");
        Map(x => x.DogsProperty);
    }
}

public class CatMap : SubclassMap<Cat>
{
    public CatMap()
    {
        this.Table("Cats");
        this.KeyColumn("AnimalId");
        Map(x => x.CatsProperty);
    }
}

使用这样的映射一切正常,但生成的模式如下所示:

Db schema

这样的代码:

 var owner = new AnimalsOwner();
                    owner.Cats.Add(new Cat()
                    {
                        AnimalsOwner = owner,
                        CatsProperty = "cat"
                    });

在列OwnderId的所有三个表(动物,猫,狗)中插入。但是仅仅在动物表中使用它还不够吗?如果是,那么如何实现呢?如果NHibernate按预期运行,那他为什么要这么重复?

2 个答案:

答案 0 :(得分:3)

我会使用每个表的策略映射它,并按类型过滤公共集合。这种数据库结构更易于使用,查询效率更高。

public class AnimalMapping : ClassMap<Animal>
{
    public AnimalMapping()
    {
        Table("Animals");
        Id(x => x.Id).GeneratedBy.Native();    
        References(x => x.AnimalsOwner);
        DiscriminateSubClassesOnColumn("AnimalType");
    }
}

public class DogMap : SubclassMap<Dog>
{
    public DogMap()
    {
        DiscriminatorValue("DOG");
        Map(x => x.DogsProperty);
    }
}

public class CatMap : SubclassMap<Cat>
{
    public CatMap()
    {
        DiscriminatorValue("CAT");
        Map(x => x.CatsProperty);
    }
}

Dogs and Cats集合可以通过将Animals集合映射为私有成员并按类型过滤来公开:

public class AnimalsOwner
{
    private IList<Animal> _animals;

    public AnimalsOwner()
    {
        _animals = new List<Animal>();
    }

    public virtual int Id { get; set; }

    public virtual IEnumerable<Animal> Animals { get { return _animals; } }

    public virtual IEnumerable<Cat> Cats { get { return _animals.OfType<Cat>(); } }

    public virtual IEnumerable<Dog> Dogs { get { return _animals.OfType<Dog>(); } }

    public virtual void AddAnimal(Animal animal)
    {
        if (!_animals.Contains(animal))
        {
            animal.AnimalsOwner = this;
            _animals.Add(animal); 
        }
    }

    public virtual void RemoveAnimal(Animal animal)
    {
        if (_animals.Contains(animal))
        {
            animal.AnimalsOwner = null;
            _animals.Remove(animal);
        |
     }   
}

此课程的映射是:

public OwnerMapping()
    {
        this.Table("Owners");
        Id(x => x.Id).GeneratedBy.Native();

        HasMany(x => x.Animals.AsBag.Cascade.AllDeleteOrphan()
            .Inverse().LazyLoad()
            .Access.CamelCaseField(Prefix.Underscore);
    }
}

添加猫的代码是:

var owner = new AnimalsOwner();
owner.AddAnimal(new Cat()
                {
                    CatsProperty = "cat"
                });

答案 1 :(得分:0)

您将获得重复项,因为您在所有者映射中定义了HasMany Cats and Dogs(以及Owner类中的Cat&amp; Dog集合)。也许您真正想要的是所有者类中的动物集合(不是单独的狗和猫)以及所有者映射中的一个HasMany动物?