Запросы NHibernate Criteria — как использовать в отношениях «один к одному»

#nhibernate #entity-relationship #nhibernate-criteria

#nhibernate #сущность-отношение #nhibernate-критерии

Вопрос:

У меня есть простые 3 класса POCO:

 public class User
{
    //PK
    public virtual int UserId { get; set; }
    //ONE to ONE
    public virtual Profil Profil{ get; set; }
    //ONE to MANY
    public virtual IList<PhotoAlbum> Albums { get; set; }
}

public class Profil
{
    //PK
    public virtual int ProfilId { get; set; }

    public virtual int Age { get; set; }
    public virtual int Sex { get; set; }
}

public class PhotoAlbum
{
    //PK
    public virtual int PhotoAlbumId { get; set; }

    public virtual string Name { get; set; }
    public virtual int NumberOfPhoto { get; set; }
}
 

Я создал эти классы сопоставления:

 public class UserMap : ClassMap<User>
    {
        public UserMap()
        {
            //PK
            Id(p => p.UserId)
               .GeneratedBy.Identity();
            //FK
            References(p => p.Profil)
                .Column("ProfilId")
                .Cascade.All(); 
            //ONE TO MANY
            HasMany(p => p.Albums)
                 .Cascade.All();

            Table("Users");
        }
    }

    public class ProfilMap: ClassMap<Profil>
    {
        public ProfilMap()
        {
            Id(p => p.ProfilId)
                .GeneratedBy.Identity();

            Map(p => p.Age)
                .Not.Nullable();
            Map(p => p.Sex)

            Table("Profiles");
        }
    }

    public class PhotoAlbumMap : ClassMap<PhotoAlbum>
    {
        public PhotoAlbumMap()
        {
            Id(p => p.PhotoAlbumId)
                .GeneratedBy.Identity();
            Map(p => p.Name)
                .Not.Nullable();
            Map(p => p.NumberOfPhoto)
                .Not.Nullable();
            Table("PhotoAlbums");
        }
    }
 

Затем я создал простой класс репозитория NHibernate с помощью этого метода:

     public IList<T> GetItemsByCriterions(params ICriterion[] criterions)
    {
        ICriteria criteria = AddCriterions(_session.CreateCriteria(typeof(T)),
            criterions);

        IList<T> result = criteria.List<T>();
        return result ?? new List<T>(0);
    }
 

Для теста я создал репозиторий для некоторого объекта, например пользователя:

 _userRepo = new NHibRepository<User>(NHibeHelper.OpenSession());
 

и я хотел бы иметь возможность сделать запрос в этом стиле:

     var users = _userRepo.GetItemsByCriterions(new ICriterion[]
                                                   {
                                                       Restrictions.Gt("Profile.Age",10)
                                                   });
 

эта попытка завершилась ошибкой:

не удалось разрешить свойство: Профиль: Repository.User

Пользователь имеет свойство Profile тип профиля, и это свойство имеет свойства ProfileID, Возраст и пол.

** ОТРЕДАКТИРОВАНО #1:**

@ Я попробовал это:

     var users = _userRepo.GetItemsByCriterions(new ICriterion[]
                                                   {
                                                       Restrictions.Where<User>(u=>u.Profil.Sex==0)
                                                   });
 

закончено с ошибкой:

не удалось разрешить свойство: Профиль.Пол: Репозиторий.Пользователь

#2 ОТРЕДАКТИРОВАНО

Я попытался воспользоваться советом Натана:

         var result = _userRepo.Session.CreateCriteria<User>()
            .CreateAlias("Profile", "profile", JoinType.InnerJoin)
            .Add(Restrictions.Eq("profile.Sex", 0));

        IList<User> users=null;
        if (result != null)
            users = result.List<User>();
 

Если я попытаюсь преобразовать результат в список, я снова получу эту ошибку: не удалось разрешить свойство: Profile of: Repository.User

Ответ №1:

Глядя на ваш пример, пользователь имеет свойство Profil, а не свойство Profile.

Если предполагается, что это Profil, я бы изменил Restrictions.Gt(Profile.Age,10) , чтобы Restrictions.Gt(Profil.Age,10) в противном случае изменить имя свойства и сопоставления в соответствии с запросом.

Редактировать:
Вы пытаетесь запросить пользовательский объект. вам необходимо включить createAlias, чтобы nhibernate знал, что вы хотите связать с другим объектом.

Попробуйте это.

 var users = session.CreateCriteria<User>() 
  .CreateAlias("Profile", "profile", JoinType.InnerJoin) 
  .Add(Restrictions.Eq("profile.Age", 10)); 
 

Комментарии:

1. Спасибо за совет, но когда я попытался преобразовать пользователей в список <User>, я снова получил то же исключение: не удалось разрешить свойство: Profile of: Repository.User

2. Я создал репозиторий bitbucket bitbucket.org/gonefishern/so_7952683 с очень простым тестовым приложением, которое показывает, что оно работает. если вы загружаете исходный код, вам нужно будет установить пакеты fluentnhibernate и SqlServerCompact