1

假设以下类:

public class A
{
  public virtual ind Id { get; set; }
  public virtual int Number { get; protected set; }
}

public class B : A
{
  public virtual string SomeValue { get; set; }

  public virtual int BookingNumber
  {
    get { return Number; }
    set { Number = value; }
  }
}

public class C : A
{
  public virtual string SomeOtherValue { get; set; }

  public virtual int AccountNumber
  {
    get { return Number; }
    set { Number = value; }
  }
}

如您所见,我想以不同的名称公开属性 Number 。

现在我想映射 A、B、C。

public class AMap : ClassMap<A>
{
  public AMap()
  {
    Id(x => x.Id);
    Map(x => x.Number);
  }
}

public class BMap : SubclassMap<B>
{
  public BMap()
  {
    Map(x => x.SomeValue);
  }
}

public class CMap : SubclassMap<C>
{
  public CMap()
  {
    Map(x => x.SomeOtherValue);
  }
}

使用此映射,我可以将内容保存到数据库中。

但是,当我查询 B 或 C 时:

Session.QueryOver<B>().Where(x => x.BookingNumber).List();

我收到错误could not resolve property: BookingNumber of: B

我究竟做错了什么?

4

1 回答 1

2

怎么了?在未映射的属性上构建查询。

(在派生类中使用不同名称包装基本属性至少很奇怪),如果确实需要这种方法,因为某些上层需要为同一属性使用不同的名称......那么,好吧。但是,NHibernate 必须提供不同的信息集。

考虑一下您的查询,作为自我描述信息,包含足以转换为 SQL 语句的信息。

所以如果你使用QueryOver<B>.Where(x => x.BookingNumber == 1).... 信息是(在解析 lambda 表达式时):

  1. 使用 C# 对象B
  2. 找到它的属性BookingNumber
  3. 找到它的映射表示:列名BookingNumberColumn
  4. 取值:1
  5. 建立了一个查询WHERE BookingNumberColumn = 1

在这种情况下,第 3 步失败。没有列映射到BookingNumber...

解决方案是,至少在数据(NHibernate)层上,应用基于基类A映射的过滤器

Session
  .QueryOver<B>()
  .Where(x => x.Number == 1) // use the A.Number MAPPED property
  .List<B>();

但是,根据我的经验,我们主要做的是转换持久性的差异(不同的 id 列名称,不同的代码列)并将它们映射到 C# 基类或具有通用、简化结构的接口。

更多内容:16. QueryOver 查询

于 2013-02-07T04:54:13.847 回答