Nhibernate类中相同类型的多个组件属性

Nhibernate类中相同类型的多个组件属性,nhibernate,hibernate,properties,components,Nhibernate,Hibernate,Properties,Components,我有一个类行,它包含两个POINT类型的属性。 我想点是一个组件属性。 若该行只包含1个点,那个么这并没有问题,但由于它包含2个点,我认为我需要区分它们(所以可以将前缀或后缀应用于列名)。 我尝试使用ComponentProperty标记的PropertyName属性,但在我的行表中仍然只生成一组X和Y列 为了清楚起见,我的目标是创建一个包含Point1_X、Point1_Y、Point2_X和Point2_Y列的行表 我使用Nhibernate.Mapping.Attributes,下面您可以

我有一个类行,它包含两个POINT类型的属性。 我想点是一个组件属性。 若该行只包含1个点,那个么这并没有问题,但由于它包含2个点,我认为我需要区分它们(所以可以将前缀或后缀应用于列名)。 我尝试使用ComponentProperty标记的PropertyName属性,但在我的行表中仍然只生成一组X和Y列

为了清楚起见,我的目标是创建一个包含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
}

同时,我发现以下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>

在查看了Nhibernate.Mapping.Attributes的单元测试并尝试了许多不同的解决方案之后,我们发现(不幸的是)修复上述情况的最干净的方法是将一些原始xml注入到我们的映射中。这意味着我们删除了line类中的属性属性,并将其替换为一个条目,如下所示

[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>")]
[RawXml(After=typeof(ComponentAttribute),Content=@”
")]

这个问题和答案在我玩游戏时帮了我的忙

我想我应该尝试包括上述行/点实现。如果有人感兴趣,我的代码如下。我发现使用属性也有一些令人沮丧的怪癖。第一种情况是,如果使用多个具有[Id]声明的类,例如:

    [Id(Name = "id")]
    [Generator(1, Class = "native")]
然后需要为生成器指定订单号(1),否则生成的映射可能会忽略一个或多个类的生成器属性。显然,这与VS处理事情的方式有关

在将示例Pet.hbm.xml文件与生成的文件输出进行比较时,我发现的另一件事是:

//需要时导出到映射文件。测试/生产。
HbmSerializer.Default.Serialize(typeof(Pet.Assembly,“Pets.hbm.xml”);

就是不应该在[Id]属性中设置Access=“field”属性,即使它在示例映射文件中

Line和UiPoint类(在NHibernatePets命名空间中)

在公共课程中

    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();
    }
    [Id(Name = "id")]
    [Generator(1, Class = "native")]
[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; }
}
        //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();
    }