如何在Fluent NHibernate中映射不相关(无直接关系)的表

时间:2014-02-07 19:53:06

标签: c# nhibernate fluent-nhibernate

我有以下表格

  1. Car(CarId, Name,...)
  2. CarPartLink(CarId, PartId)
  3. Part(PartId, Name)
  4. SubPartLink(Parent_PartId, Child_PartId)其中父母和子女都来自Part table
  5. 我希望Car个对象包含Parts的列表,其中包含SubParts,此处Car与其Part Subparts没有直接关系PartSubparts没有直接关系。

    class Car
    {
      public virtual string Id { get; set; }
      public virtual string Name { get; set; }
      public virtual ICollection<Parts> AllParts { get; set; } //This should include all the parts and its subparts assuming subparts are only one level deep
    }
    

    如何在Fluent NHibernate中制作相同的地图?

    修改1:

    如果在Fluent NHibernate中不可能,但在NHibernate映射中可能,那么对我也没关系。

    我使用的是Fluent NHibernate版本:1.4.0.1和NHibernate版本:3.3.3

    编辑2:

    如果我只获得地图中的id个子部分或subparts,我也很好。

    编辑3:

    每辆车(此处为Car提及的示例)总共超过100万partssubparts,其中用户实际上将使用少量100件,具体取决于条件。例如获取所有重量为100 kg的零件或获得所有“螺钉”类型的零件。我将在只读模式下需要这些数据。

1 个答案:

答案 0 :(得分:1)

FluentNH wiki已经有关于关系映射的精彩教程。我建议你阅读指南,或者更好,一步一步地按照它。假设以下实体:

public class Car
{
    public virtual int CarId { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Part> AllParts {get; set;}

    public Car()
    {
        AllParts = new List<Part>();
    }
}

public class Part
{
    public virtual int PartId { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Car> AllCars {get; set;}

    //never tried mapping a many-to-many on the same entity, but this should work...
    public virtual IList<Part> ParentParts {get; set;}
    public virtual IList<Part> SubParts {get; set;}

    public Part()
    {
        AllCars = new List<Car>();
        ParentParts = new List<Part>();
        SubParts = new List<Part>();
    }   
}

你的映射可能是这样的:

public class CarMap : ClassMap<Car>
{
    public CarMap()
    {
        Id(x => x.CarId);
        Map(x => x.Name);
        HasManyToMany(x => x.AllParts)
            //depending on your logic, you would either set .Inverse here or in the PartMap
            .Table("CarPartLink")
            .ParentKeyColumn("CarId")
            .ChildKeyColumn("PartId")
            .Cascade.All();
    }
}   

public class PartMap : ClassMap<Part>
{
    public PartMap()
    {
        Id(x => x.PartId);
        Map(x => x.Name);
        HasManyToMany(x => x.AllCars)
            .Table("CarPartLink")
            .ParentKeyColumn("PartId")
            .ChildKeyColumn("CarId")
            .Cascade.All();
        HasManyToMany(x => x.ParentParts)
            .Table("SubPartLink")
            .ParentKeyColumn("Parent_PartId")
            .ChildKeyColumn("Child_PartId")
            .Inverse() //saving done from the child side of the relationship, right?
            .Cascade.All();
        HasManyToMany(x => x.SubParts)
            .Table("SubPartLink")
            .ParentKeyColumn("Child_PartId")
            .ChildKeyColumn("Parent_PartId")
            .Cascade.All();
    }
}   

如果以上情况不起作用,请告诉我。显然,某些版本的FNH中存在一个错误,您需要采用特殊的解决方法。您可以在this question中找到解决方法(通过OP查找自行提交的答案),该方法基于与您相同的方案(同一实体上的多个方案)。

编辑:如果您想获取Car的所有部分和子部分,则需要递归访问每个SubParts的{​​{1}}在您的Part集合中。

Car.AllParts

Edit2 :这blog post似乎正是您所需要的......

Car Car1 = new Car();
//code to get car object
IList<Part> AllParts = new List<Part>();
GetAllParts(Car.AllParts, ref AllParts); //call a recursive method to add all the parts and subparts to the list
//do something with the list


public void GetAllParts(IList<Part> parentList, ref IList<Part> partsList)
{
    foreach (Part part in parentList)
    {
        if (!partsList.Contains(part)) //validate if the list already contains the part to prevent replication
            partsList.Add(part); //add this part to the list
        if (part.SubParts.Count > 0) //if this part has subparts
            GetSubParts(part.SubParts, ref partsList); //add all the subparts of this part to the list too
    }
}