2010-02-09 2 views
2

У меня есть класс LINE, который содержит два свойства типа POINT. Я бы хотел, чтобы POINT был компонентом. Если LINE должен содержать только 1 POINT, это не проблема, но поскольку в нем содержится 2 POINT, я бы подумал, что мне нужно их различать (поэтому к именам столбцов можно применить префикс или суффикс). Я попытался использовать атрибут PropertyName тега ComponentProperty, но в моей таблице LINE создается только один набор столбцов X и Y.Nhibernate многокомпонентные свойства одного и того же типа в классе

Для большей ясности моя цель - иметь таблицу LINE с точками Point1_X, Point1_Y, Point2_X и Point2_Y.

Я использую 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

Я думал, что у меня есть возможность включить приведенную выше линейную/точную реализацию. Мой код ниже, если кому-то интересно. Я нашел некоторые расстраивающие причуды с использованием атрибутов. Первый в том, что если вы используете несколько классов с [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");

было то, что Access = «поле» свойство не должно быть установлено в [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); } 

В программе Public Class ...

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(); 
    } 
Смежные вопросы