【问题标题】:LINQ to NHibernate: could not resolve propertyLINQ to NHibernate:无法解析属性
【发布时间】:2010-12-13 23:50:02
【问题描述】:

使用 nHibernate v. 2.1.2.4、nHibernate.Linq v. 1.1.0.1001 和 Fluent NHibernate v. 1.1.0.685 的 Fluent nHibernate。

我有一个域对象,其中包含一个名为 DateOfEvent 的 DateTime 字段。这是数据库中的实际日期/时间字段。我还添加了 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,我已经模糊了项目的名称。 ;)

知道如何让这个查询工作吗?

谢谢! -史蒂夫

编辑: 这是我的映射类:

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

也没有工作。

【问题讨论】:

  • 奇怪。对我来说看起来不错,我想知道是否可能是 LINQ 提供者试图对这些属性做一些花哨的事情。您是否尝试过不使用 LINQ 运行相同的查询?
  • Phill,刚刚尝试使用 Criteria API(发布查询)。同样的例外。
  • 奇怪,不能说我以前遇到过这样的问题。您能否尝试从两个属性中删除虚拟。怀疑它会有所帮助,但值得一试。除此之外,我现在没有想法对不起:(
  • 奇怪,不能说我以前遇到过这样的问题。您能否尝试从两个属性中删除虚拟。不确定它是否会有所帮助,值得一试。除此之外,我没有想法。我唯一的其他建议是尝试来自 Fluent 网站的最新稳定版本。 fluentnhibernate.org/downloads
  • 已经试过了。获取此异常:以下类型不得用作代理: ...事件:方法 get_YearOfEvent 应为“公共/受保护的虚拟”或“受保护的内部虚拟” ...事件:方法 get_MonthOfEvent 应为“公共/受保护的虚拟”或“受保护的内部虚拟”

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


【解决方案1】:

以下是使用公式解决此问题的方法。在您的 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>();

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • 菲尔,我正在手动映射它们。我已经发布了我的配置以及我的映射。
        【解决方案5】:

        您的条件查询不起作用,因为您的“YearOfEvent”属性未在映射中列出。 NHibernate 不知道该属性,也无法将其转换为列名。

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

        但是,您的 linq 查询看起来应该可以正常工作,但我看不出该查询和映射是如何发生此错误的...

        【讨论】:

          猜你喜欢
          • 2010-12-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多