LINQ to NHibernate:无法解析属性

时间:2010-12-13 23:50:03

标签: nhibernate fluent-nhibernate linq-to-nhibernate

使用nHibernate v.2.1.2.4,nHibernate.Linq v.1.1.0.1001和Fluent NHibernate v.1.1.0.685进行流利的nHibernate。

我有一个名为DateOfEvent的DateTime字段的域对象。这是数据库中的实际日期/时间字段。我还添加了2个新属性YearOfEvent,它从DateOfEvent字段获取Year,以及从DateOfEvent字段获取Month的MontOfEvent。

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:.... Event

FWIW,我已经模糊了项目的名称。 ;)

知道如何使这个查询有效吗?

谢谢! -Steve

编辑: 这是我的映射类:

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;
    }

我也尝试了Criteria API:

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

也没有工作。

5 个答案:

答案 0 :(得分:4)

以下是使用公式解决问题的方法。在Event类中,将这两个属性转换为常规属性:

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语法不是很积极。一个月,但你有一个想法(我使用this参考):

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>();

答案 1 :(得分:2)

您可以查询真正存在于数据库中或在映射中引入的属性。由于YearOfEvent只存在于您的实体中,因此无法在LINQ-to-NH或ICriteria的查询中使用它。

答案 2 :(得分:2)

我使用的技术是强制执行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()。

答案 3 :(得分:1)

你是自动映射吗?因为我怀疑它试图映射YearOfEvent和MonthOfEvent,并且它试图从数据库中提取这些列,但它们不存在。

如果你手动映射它们,那么这不是问题。

答案 4 :(得分:0)

您的条件查询无效,因为您的“YearOfEvent”属性未在您的映射中列出。 NHibernate不知道这个属性,也不能将它转换为列名。

尝试查询实际映射的属性而不是计算属性,或直接在查询中计算属性...

然而,您的linq查询看起来应该正常工作,我不知道该查询&amp;映射...