[英]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
映射到File1
和File2
? 我可以使用很多方法來定義用於關系的哪一列嗎? ( Error
一側。)
使用基類
對於這種情況,映射基類是一種常見的解決方案。 這要求您的ID在File1
和File2
之間必須是唯一的。 (沒有現成的復合ID File1
中可以找到File2
,反之亦然。)對於具有兩個distintc表File1
和File2
,而沒有基類的表,你必須使用“每個具體類策略表” 。
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在File1
和File2
唯一性,則必須將它們映射為兩個單獨的實體集合。
您的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
映射為File1
和File2
中的組件列表,而不是將Error
映射為實體。 我不太了解Fluent,所以只能用hbm語法說明這一點。 您可以自行找到合適的Fluent電話。
這要求您的ID在File1
和File2
也必須是唯一的,否則錯誤可能會混雜在一起。 (相反,在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
,則組件將必須實現Equals
和GetHashCode
重寫,並且Description
必須不能為空。
使用多對任何
再說一遍,我不知道Fluent是否會處理。 我也從未嘗試過,文檔也很簡潔。 無論如何,這是一個外來的映射,以盡可能避免。 它需要一個附加列來標識什么是“ any” 。 它將允許您將錯誤的文件引用映射為單個對象屬性,而無需基類。 並且它將支持具有共同ID的File1
和File2
。
筆記:
如果將其保留為實體而不是組件,則應在Error
類上添加主鍵。 一個技術序列號或類似的編號。
最好避免使用復合ID 。 否則,將它們映射為復合標識符 ,並在其組件和實體中覆蓋Equals
和GetHashCode
。
您不需要在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.