NHibernate - 转换为类中的类?

时间:2016-03-30 11:58:42

标签: c# nhibernate

当我尝试将返回的数据从SQL转换为具有类内部的类时,我不断遇到NHibernate的恼人错误。让我说这些课程。

[DataContract()]
public class Person {
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public Dog Dog { get; set; }
}
[DataContract()]
public class Dog {
    [DataMember]
    public int Age { get; set; }
}

我有这个SQL查询。

SELECT
    p_name AS 'Name',
    p_dog_age AS 'Dog.Age'
FROM People WHERE p_name = 'Foo';

并将其转换为Person class I

var person = Session.CreateSQLQuery(Sql.GetPerson)
                .SetResultTransformer(new AliasToBeanResultTransformer(typeof(Person)))
                .Future<Person>().FirstOrDefault();

每当我这样做时,我都会收到以下错误

An exception of type 'NHibernate.PropertyNotFoundException' occurred in NHibernate.dll but was not handled in user code

抱怨它无法找到Dog.Age的属性,并且它没有setter属性。我知道应该可以做到这一点,但我无法弄明白。

我知道从SQL查询返回的值不为空。

2 个答案:

答案 0 :(得分:1)

听起来你正试图映射一个组件。 使用FluentNHibernate:

public class PersonMap : ClassMap<Person>
{ 
    public PersonMap() 
    {
        Table("Person");
        Id(p => p.Id, "Id").GeneratedBy.Native().Not.Nullable();
        Map(p => p.Name, "Name").Length(255).Not.Nullable();

        Component(p => p.Dog, d =>
        {
            d.Map(dog => dog.Name, "DogName").Not.Nullable();
            d.Map(dog => dog.Age, "DogAge").Not.Nullable();
        }
    }    
}

你需要一个包含4列的表格:

  • ID
  • 姓名(人名)
  • dogname(该人的狗的名字)
  • dogage(该人的狗的年龄)
但是 - 如果一个人有两只狗怎么办?还是没有狗?

public class PersonMap : ClassMap<Person>
{ 
    public PersonMap() 
    {
        Table("Person");
        Id(p => p.Id, "Id").GeneratedBy.Native().Not.Nullable();

        References(p => p.Dog, "Dog").Nullable();
    }
}

public class DogMap : ClassMap<Dog>
{
    Map(d => d.Id, "Id").GeneratedBy.Native();

    References(p => p.Person, "Person").Nullable();
    Map(d => d.Name, "Name").Not.Nullable();
    Map(d => d.Age, "Age").Not.Nullable();
    }    
}

这需要两个表,并且会受益于几个引用Id的外键。

使用NHibernate的Linq实现,您可以直接从一个人查询狗的姓名和年龄:

var dog = 
   _session.Query<Person>()
           .Where(p => p.Name == "Charlie Brown")
           .Where(p => p.Dog.Name == "Snoopy")
           .Select(p => p.Dog)
           .SingleOrDefault();

答案 1 :(得分:0)

<强>解决方案

在环顾四周并尝试了一些不同的方法后,我想出了这个。

private void doStuff(){
    var listOfRows = Session.CreateSQLQuery(Sql.GetPerson)
        .List();

    var listOfPersonRows = new List<Person>();

    if (listOfRows.Count != 0)
    {
        for (var i = 0; i < listOfRows.Count; i++)
        {
            var item = (object[])listOfRows[i];
            listOfPersonRows.Add(ConvertToRow(item));
        }
    }
}

private Person ConvertToRow(object[] item)
{
    var personRow = new Person();

    personRow.Name = (string)item[0];
    personRow.Dog.Age = (int)item[1];


    return personRow;
}

这样我仍然只需要一次查询数据库而不是多次。