LINQ to NHibernate: не удалось разрешить свойство - PullRequest
3 голосов
/ 14 декабря 2010

Fluent nHibernate с использованием nHibernate v. 2.1.2.4, nHibernate.Linq v. 1.1.0.1001 и Fluent NHibernate v. 1.1.0.685.

У меня есть объект домена с полем DateTime с именем DateOfEvent. Это фактическое поле даты / времени в базе данных. Я также добавил 2 новых свойства YearOfEvent, которые получают год из поля DateOfEvent, а также MontOfEvent, который получает месяц из поля DateOfEvent.

public class Event
{
    public Event() { }
    public virtual Int32 Id { get; set; }
    public virtual String Title { get; set; }
    public virtual DateTime DateOfEvent { get; set; }
    public virtual Int32 YearOfEvent
    {
        get { return DateOfEvent.Year; }
    }
    public virtual Int32 MonthOfEvent
    {
        get { return DateOfEvent.Month; }
    }
    public virtual String Location { get; set; }
    public virtual String City { get; set; }
    public virtual String State { get; set; }
    public virtual String Zip { get; set; }
    public virtual String Description { get; set; }
    public virtual Boolean HasImage { get; set; }
    public virtual Boolean IsActive { get; set; }
}

Однако при запуске этого метода:

public IList<Event> GetActiveEvents(int pageNumber, int pageSize, out int totalItems)
    {
        Int32 skip = Misc.NumberToSkip(pageNumber, pageSize);
        totalItems = (from e in _session.Linq<Event>()
                      where e.IsActive
                      select e).Count();

        return (from e in _session.Linq<Event>()
                where e.IsActive
                select e)
            .Skip(skip)
            .Take(pageSize)
            .ToList();
    }

NHibernate.QueryException: не удалось разрешить свойство: YearOfEvent of: .... Event

FWIW, я размыл название проекта. ;)

Есть идеи, как заставить этот запрос работать?

Спасибо! -Стив

EDIT: Вот мой класс картографии:

public class EventMap : ClassMap<Event>
{
    public EventMap()
    {
        Table("tbl_event");
        Id(x => x.Id, "eventId");
        Map(x => x.DateOfEvent, "dateOfEvent");
        Map(x => x.Description, "description");
        Map(x => x.Title, "title");
        Map(x => x.Location, "location");
        Map(x => x.State, "state");
        Map(x => x.City, "city");
        Map(x => x.Zip, "zip");
        Map(x => x.HasImage, "hasImage");
        Map(x => x.IsActive, "isActive");
    }
}

... и мой конфиг:

public Configuration GetConfiguration()
    {
        Configuration configuration;
        var assembly = Assembly.Load(".....Data");
        var fluentConfig = Fluently.Configure()
                            .Database(MySQLConfiguration.Standard.ConnectionString(
                                          c => c.FromConnectionStringWithKey("......")
                                          ))
                            .Mappings(m => m.FluentMappings.AddFromAssembly(assembly));
        configuration = fluentConfig.BuildConfiguration();
        configuration.Properties.Add("hbm2ddl.keywords", "none");
        return configuration;
    }

Я также только что попробовал API Criteria:

return _session.CreateCriteria(typeof (Event))
            .Add(Expression.Eq("IsActive", true))
            .Add(Expression.Eq("YearOfEvent", year))
            .List<Event>();

Работника тоже нет.

Ответы [ 5 ]

4 голосов
/ 15 декабря 2010

Вот как это можно исправить с помощью формул. В вашем классе Event конвертируйте эти 2 свойства в обычные свойства:

public class Event
{
    public Event() { }
    ...
    public virtual DateTime DateOfEvent { get; set; }
    public virtual Int32 YearOfEvent{ get; set; }
    public virtual Int32 MonthOfEvent { get; set; }
    ...
    public virtual Boolean IsActive { get; set; }
}

Затем в сопоставлении добавьте формулы для заполнения их значений. Я не очень уверен в синтаксисе MySQL для получения года и месяца, но у вас есть идея (я использовал эту ссылку) :

public class EventMap : ClassMap<Event>
{
    public EventMap()
    {
        Table("tbl_event");
        Id(x => x.Id, "eventId");
        Map(x => x.DateOfEvent, "dateOfEvent");
        Map(x => x.YearOfEvent).Formula("SELECT YEAR(dateOfEvent)");
        Map(x => x.MonthOfEvent).Formula("SELECT MONTH(dateOfEvent)");            
        ...
        Map(x => x.IsActive, "isActive");
    }
}

Теперь вы можете запрашивать их, как и любые другие поля, используя LINQ или ICriteria:

return _session.CreateCriteria(typeof (Event))
            .Add(Expression.Eq("IsActive", true))
            .Add(Expression.Eq("YearOfEvent", year))
            .List<Event>();
2 голосов
/ 14 февраля 2011

Техника, которую я использую, состоит в том, чтобы принудительно запустить NHLinq, а затем использовать LINQ для завершения фильтрации. Технически это то, что должно произойти, так как NH не знает о неотображенных свойствах, таких как Event.YearOfEvent. Это будет выглядеть примерно так:

_session.Linq<Event>()
.Where(e => e.IsActive)
.ToArray() // force evaluation of expression
.Where(e => e.YearOfEvent == DateTime.Now.Year); // evaluated by LINQ, not NHLinq

Примечание. Вы можете использовать любой из других методов, которые форсируют оценку (например, ToList ()). Этот метод не зависит конкретно от ToArray ().

2 голосов
/ 14 декабря 2010

Вы можете запрашивать свойства, которые действительно существуют в базе данных или представлены в отображениях. Поскольку YearOfEvent существует только в вашей организации, вы не можете использовать его в своих запросах ни в LINQ-to-NH, ни в ICriteria.

1 голос
/ 14 декабря 2010

Вы автоматически отображаете это?Поскольку я подозреваю, что он попытался отобразить YearOfEvent и MonthOfEvent, и он пытается извлечь эти столбцы из базы данных, но они не существуют.

Если вы сопоставляете их вручную, то это невопрос.

0 голосов
/ 14 декабря 2010

Ваш запрос критерия не работает, потому что ваше свойство YearOfEvent не указано в вашем отображении. NHibernate не знает это свойство и не может перевести его в имя столбца.

Попробуйте запросить свойства, которые на самом деле отображаются вместо вычисляемых свойств, или рассчитать свойство непосредственно в вашем запросе ...

Однако ваш запрос linq выглядит так, как будто он должен работать, я не понимаю, как эта ошибка может возникать с этим запросом и отображением ...

...