2010-02-09 67 views
2

我有一個包含POINT類型兩個屬性的類LINE。 我希望POINT是一個組件屬性。 如果LINE只包含1個POINT,這將是沒有問題的,但是由於它包含2個POINT,我認爲我需要區分它們(所以前綴或後綴可以應用於列名)。 我嘗試使用ComponentProperty標籤的PropertyName屬性,但仍然只有一組X和Y列在我的LINE表中生成。在一個類中同一類型的Nhibernate多個組件屬性

爲了清楚起見,我的目標是創建一個包含Point1_X,Point1_Y,Point2_X和Point2_Y列的LINE表。

我用Nhibernate.Mapping.Attributes,下面你可以看到我的映射

[Class] 
public class Line : EntityBase 
{ 
    [ComponentProperty(PropertyName = "Point1")] 
    public UiPoint Point1 { get; set; } 

    [ComponentProperty(PropertyName = "Point2")] 
    public UiPoint Point2 { get; set; } 

    //omitted the constructor 

}

[Component] 
public class UiPoint 
{ 
    [Property] 
    public double X { get; set; } 

    [Property] 
    public double Y { get; set; } 

    //omitted the constructor 
} 

在我想通了,與此同時以下XML映射西港島線解決我的問題

<class name="Domain.WashProcessLine,Domain"> 
    <id name="Id" /> 
    <component name="Point1"> 
     <property name="X" type="Double" column="Point1_X" /> 
     <property name="Y" type="Double" column="Point1_Y" /> 
    </component> 
    <component name="Point2"> 
     <property name="X" type="Double" column="Point2_X" /> 
     <property name="Y" type="Double" column="Point2_Y" /> 
    </component> 
</class> 

找到一個選項https://www.hibernate.org/hib_docs/nhibernate/html/components.html

下面的標記會創建所需的表結構,但在從數據庫中檢索屬性時會給我一個轉換異常(從UiPoint到IDictionary)。

所以我不完全有尚未:(

[Class] 
public class Line : EntityBase 
{ 
    [DynamicComponent(1)]    
    [Property(2, Name = "X", Column = "Point1_X", TypeType = typeof(double))] 
    [Property(3, Name = "Y", Column = "Point1_Y", TypeType = typeof(double))] 
    public UiPoint Point1 { get; set; } 

    [DataMember] 
    [DynamicComponent(1)]    
    [Property(2, Name = "X", Column = "Point2_X", TypeType = typeof(double))] 
    [Property(3, Name = "Y", Column = "Point2_Y",TypeType=typeof(double))] 
    public UiPoint Point2 { get; set; } 
} 

回答

1

看單元測試Nhibernate.Mapping.Attributes,並嘗試了一些不同的解決方案後,我們發現,最徹底的方法(很遺憾)以固定上述提供的情況下,通過注入一些原始XML到我們的映射。這意味着我們除去場所在我們的線類屬性和具有單條目代之以如下所示

[RawXml(After=typeof(ComponentAttribute), Content = @"<component name=""Point1""> 
<property name=""X"" type=""Double"" column=""Point1_X"" /> 
    <property name=""Y"" type=""Double"" column=""Point1_Y"" /> 
</component> 
<component name=""Point2""> 
    <property name=""X"" type=""Double"" column=""Point2_X"" /> 
    <property name=""Y"" type=""Double"" column=""Point2_Y"" /> 
</component>")] 
0

這個問題和答案在玩wi時幫助我th NHibernatePets Sample

我想我會去包括上面的線/點實施。如果有人感興趣,我的代碼在下面。我也發現了一些使用Attributes的令人沮喪的怪癖。第一個是,如果使用的是多個類與[ID]聲明如:

[Id(Name = "id")] 
    [Generator(1, Class = "native")] 

則需要指定的順序號(1),用於發電機或其他所生成的映射可以省略用於生成屬性一個或多個你的課程。顯然這與VS處理事物的方式有關。

再就是使用示例Pet.hbm.xml文件,生成的文件輸出進行比較時,我發現:

//Export to a mapping file when required. Test/Production. HbmSerializer.Default.Serialize(typeof(Pet).Assembly,"Pets.hbm.xml");

是,訪問=「字段」屬性不應該在設置[Id]屬性,即使它在示例映射文件中。

行和UiPoint類(在NHibernatePets命名空間中)...

[Class(Lazy = true)] 
public class Line 
{ 

    [Id(Name = "id")] 
    [Generator(1, Class = "native")] 
    #if useAttributes 
     virtual public int id { get; set; } 
    #else 
     private int id; 
    #endif 

    const string point1 = 
    @"<component name= ""Point1"" class= ""NHibernatePets.UiPoint"" > 
     <property name=""X"" 
       type=""Double"" 
       column=""Point1_X""/> 
     <property name=""Y"" 
       type=""Double"" 
       column=""Point1_Y""/> 
     </component>"; 

    const string point2 = 
    @"<component name=""Point2"" class=""NHibernatePets.UiPoint"" > 
      <property name=""X"" 
       type=""Double"" 
       column=""Point2_X""/> 
      <property name=""Y"" 
       type=""Double"" 
       column=""Point2_Y""/> 
     </component>"; 

    [RawXml(After = typeof(ComponentAttribute), Content = point1)] 
    virtual public UiPoint Point1 { get; set; } 

    [RawXml(After = typeof(ComponentAttribute), Content = point2)] 
    virtual public UiPoint Point2 { get; set; } 

} 

//Don't need any Attributes set on this class as it's defined in the RawXml. 
public class UiPoint 
{ 
    public double X { get; set; } 
    public double Y { get; set; } 
} 

在main()...

 //Create the Line record 
     Line newLine = new Line 
     { 
      Point1 = new UiPoint { X = 100.1, Y = 100.2 }, 
      Point2 = new UiPoint { X = 200.1, Y = 200.2 } 
     }; 
     try 
     { 
      using (ISession session = OpenSession()) 
      { 
       using (ITransaction transaction = session.BeginTransaction()) 
       { 
        session.Save(newLine); 
        transaction.Commit(); 
       } 
       Console.WriteLine("Saved NewLine to the database"); 
      } 
     } 
     catch (Exception e) 
     { Console.WriteLine(e); } 

公共類節目...

static ISessionFactory SessionFactory; 
    static ISession OpenSession() 
    { 

     if (SessionFactory == null) //not threadsafe 
     { //SessionFactories are expensive, create only once 
      Configuration configuration = new Configuration(); 

      #if useAttributes 
      { 
       configuration.SetDefaultAssembly("NHibernatePets"); 
       //configuration.SetDefaultAssembly(System.Reflection.Assembly.GetExecutingAssembly().ToString()); 
       //To use Components and other structures, AssemblyName must be set. 
       //configuration.SetDefaultAssembly(typeof(Pet).Assembly.ToString()); 
       configuration.AddInputStream(NHibernate.Mapping.Attributes.HbmSerializer.Default.Serialize(typeof(Pet).Assembly)); 
      } 
      #else 
       configuration.AddAssembly(Assembly.GetCallingAssembly()); 
      #endif 

      //Export to a mapping file when required. Test/Production. 
      HbmSerializer.Default.Serialize(typeof(Pet).Assembly,"Pets.hbm.xml"); 

      SessionFactory = configuration.BuildSessionFactory(); 
     } 
     return SessionFactory.OpenSession(); 
    } 
相關問題