在没有对象属性的Fluent NHibernate中映射外键

时间:2013-07-13 02:21:53

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

我的问题是,对于父对象和子对象是否有可能的Fluent NHibernate映射,它不需要Child对象具有Parent对象属性?我还没弄明白如何将引用映射回Parent。当我使用映射调用Create时,我得到一个异常,因为Child对象没有所需的外键(在数据存储中需要)回到Parent。

我有两个POCO课程:

public class Parent
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Child> Childs { get; set; }
}

public class Child
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual int ParentId { get; set; }
}

还有一些映射:

public class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        this.Table("Parents");
        this.Id(x => x.Id);
        this.Map(x => x.Name);
        this.HasMany(x => x.Childs).KeyColumn("ChildId").Cascade.AllDeleteOrphan();
    }
}

public class ChildMap : ClassMap<Child>
{
    public ChildMap()
    {
        this.Table("Childs");
        this.Id(x => x.Id);
        this.Map(x => x.Name);
        // Needs some sort of mapping back to the Parent for "Child.ParentId"
    }
}

并创建方法:

public Parent Create(Parent t)
{
    using (this.session.BeginTransaction())
    {
        this.session.Save(t);
        this.session.Transaction.Commit();
    }
    return t;
}

我希望能够创建一个具有Child对象列表的Parent对象,但不能让Child对象返回其父对象(除了Parent ID)。我想这样做是为了避免从Parent到Childs列表的循环引用回到Parent对象,因为这会导致JSON序列化问题。

1 个答案:

答案 0 :(得分:3)

您可以毫无问题地映射这些实体,试试这个:

public class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        this.Table("Parents");
        this.Id(x => x.Id);
        this.Map(x => x.Name);
        this.HasMany(x => x.Childs).KeyColumn("ChildId").Cascade.AllDeleteOrphan();
    }
}

public class ChildMap : ClassMap<Child>
{
    public ChildMap()
    {
        this.Table("Childs");
        this.Id(x => x.Id);
        this.Map(x => x.Name);
        this.Map(x => x.ParentId);
        // if you have a reference of Parent object, you could map as a reference, for sample:
        this.References(x => x.Parent).Column("ParentId");
    }
}

当你从ISession获取实体时,不要将它序列化为某种格式,因为它们可以是nhibernate代替实体对象。尝试创建DTO (Data Transfer Object) classes并将这些实体转换为DTO对象,并对其进行序列化。你会避免循环引用。样本:

public class ParentDTO
{   
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }

    /* here you just have the primitive types or other DTOs, 
       do not reference any Entity type*/
}

当您需要读取值以共享序列化值时:

var dto = ISession.Query<Parent>()
                  .Select(x => 
                      new ParentDTO() { 
                           Id = x.Id, 
                           Name = x.Name, 
                           ParentId = x.ParentId)
                  .ToList();

从数据访问层获取此结果并尝试序列化,样本:

var result = Serialize(dto);