簡體   English   中英

使用Fluent NHibernate將實體之間的關系映射到其他兩個實體

[英]Mapping a relationship from an entity to two other entities with Fluent NHibernate

我用Fluent NHibernate映射了兩個不同的類

public class File1Map: ClassMap<File1> {
    CompositeId()
       .KeyProperty(x => x.IdFile)
       .KeyProperty(x => x.IdRow);

    HasMany(x => x.Errors).AsBag().KeyColumns.Add("IdFile", "IdRow");
}

public class File2Map: ClassMap<File2> {
    CompositeId()
       .KeyProperty(x => x.IdFile)
       .KeyProperty(x => x.IdRow);

    HasMany(x => x.Errors).AsBag().KeyColumns.Add("IdFile", "IdRow");
}

public class File1 {
    public int IdFile {get; set;}
    public int IdRow {get; set;}
    public List<Error> Errors {get; set;}
    // ...other properties different from File2
}

public class File2 {
    public int IdFile {get; set;}
    public int IdRow {get; set;}
    public List<Error> Errors {get; set;}
    // ...other properties different from File1
}

還有一個帶有錯誤的類,其中包含每個類的描述。

public class ErrorMap: ClassMap<Error> {
    Map(p => p.IdFile);
    Map(p => p.IdRow);
    Map(p => p.Description);
}

public class Error {
    public int IdFile {get; set;}
    public int IdRow {get; set;}
    public string Description {get; set;}
}

如何將Error映射到File1File2 我可以使用很多方法來定義用於關系的哪一列嗎? Error一側。)

使用基類

對於這種情況,映射基類是一種常見的解決方案。 這要求您的ID在File1File2之間必須是唯一的。 (沒有現成的復合ID File1中可以找到File2 ,反之亦然。)對於具有兩個distintc表File1File2 ,而沒有基類的表,你必須使用“每個具體類策略表”

public class FileBaseMap: ClassMap<FileBase> {
    CompositeId()
       .KeyProperty(x => x.IdFile)
       .KeyProperty(x => x.IdRow);

    HasMany(x => x.Errors).AsBag().KeyColumns.Add("IdFile", "IdRow");
    // One table per concrete class.
    UseUnionSubclassForInheritanceMapping();
}

public class File1Map: SubclassMap<File1> {
    // Other properties mapping
}

public class File2Map: SubclassMap<File2> {
    // Other properties mapping
}

public abstract class FileBase {
    public int IdFile {get; set;}
    public int IdRow {get; set;}
    public List<Error> Errors {get; set;}
}

public class File1 : FileBase {
    // ...other properties different from File2
}

public class File2 : FileBase {
    // ...other properties different from File1
}

然后,您可以將Error類映射到FileBase屬性。

使用單獨的外鍵

如果不想引入基類,或者不能保證文件ID在File1File2唯一性,則必須將它們映射為兩個單獨的實體集合。

您的Error類如下所示:

public class Error {
    public int? IdFile1 {get; set;}
    public int? IdRow1 {get; set;}
    public int? IdFile2 {get; set;}
    public int? IdRow2 {get; set;}
    public string Description {get; set;}
    public File1 File1 {get; set;}
    public File2 File2 {get; set;}
}

使用組件

可以將Error映射為File1File2 中的組件列表,而不是將Error映射為實體。 我不太了解Fluent,所以只能用hbm語法說明這一點。 您可以自行找到合適的Fluent電話。

這要求您的ID在File1File2也必須是唯一的,否則錯誤可能會混雜在一起。 (相反,在File1應該找不到File2存在的復合ID。)

<class name="File1">
  <!-- id and other properties here -->

  <bag name="Errors" table="Error">
    <key>
      <column name="IdFile" />
      <column name="IdRow" />
    </key>
    <composite-element class="Error">
      <property name="Description" />
    </composite-element>
  </bag>
</class>

File2

Error類將不包含文件ID屬性或文件屬性,而僅包含其Description和其他屬性(如果有)。

如果除外鍵之外,您的Error類中僅包含Description ,則最好刪除該類,然后將Errors映射為元素集合 (在您的情況下為字符串)。

如果要使用set而不是bag ,則組件將必須實現EqualsGetHashCode重寫,並且Description必須不能為空。

使用多對任何

再說一遍,我不知道Fluent是否會處理。 我也從未嘗試過,文檔也很簡潔。 無論如何,這是一個外來的映射,以盡可能避免。 它需要一個附加列來標識什么是“ any” 它將允許您將錯誤的文件引用映射為單個對象屬性,而無需基類。 並且它將支持具有共同ID的File1File2

筆記:

如果將其保留為實體而不是組件,則應在Error類上添加主鍵。 一個技術序列號或類似的編號。

最好避免使用復合ID 否則,將它們映射為復合標識符 ,並在其組件和實體中覆蓋EqualsGetHashCode

您不需要在Error映射外鍵ID,這與文件實體的映射有點多余。 您可以使Error類僅包含其Description屬性和文件實體屬性。

因此對於基類的情況是:

public class Error {
    public FileBase File {get; set;}
    public string Description {get; set;}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM