Многокомпонентные свойства Nhibernate одного и того же типа в классе - PullRequest
2 голосов
/ 09 февраля 2010

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

Для ясности моя цель - создать таблицу 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; }
}

Ответы [ 2 ]

1 голос
/ 09 февраля 2010

Посмотрев на модульные тесты для 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 голосов
/ 07 января 2011

Этот вопрос и ответ помог мне во время игры с NHibernatePets Sample

Я подумал, что мне стоит включить вышеописанную реализацию Line / Point. Мой код ниже, если кому-то интересно. Я нашел некоторые неприятные причуды с использованием атрибутов тоже. Во-первых, если вы используете несколько классов с объявлениями [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 = "field" не должно устанавливаться в атрибуте [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; }
}

In 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();
    }
...