为什么不'nhibernate支持这个“存在列表”语法?

时间:2010-12-31 19:48:01

标签: c# linq nhibernate fluent-nhibernate

我有以下查询,并且在Nhibernate 3 LINQ中失败并出现“不受支持”的异常。它similar to this question,但这个问题是在一年前提出来的,所以我很肯定答案是过时的。

我的数据库表格是:

  1. VacationRequest(id,personId)
  2. VacationRequestDate(id,vacationRequestId)
  3. 人(id,FirstName,LastName)
  4. 我的实体是:

    1. VacationRequest(Person,IList)
    2. VacationRequestDate(VacationRequest,Date)
    3. 以下是获得“不支持”异常的查询

       Session.Query<VacationRequestDate>()
         .Where(r => people
           .Contains(r.VacationRequest.Person, new PersonComparer()))
         .Fetch(r=>r.VacationRequest)
         .ToList();
      

      有没有更好的方法来编写Nhibernate支持的内容?

      fyi。 。比较人员比较人.Id

3 个答案:

答案 0 :(得分:2)

nhibernate无法翻译您应该更改的new PersonComparer()

答案 1 :(得分:1)

NHibernate不理解PersonComparer类型,因此无法将其用法转换为SQL。

您是否尝试使用不接受比较器的Contains重载? NHibernate应该推断您正在比较实体实例并在SQL比较中正确使用ID(它还能使用什么?):

Session.Query<VacationRequestDate>()
    .Where(r => people.Contains(r.VacationRequest.Person))
    .Fetch(r => r.VacationRequest)
    .ToList();

另外,请记住,在单个NHibernate会话中,始终为相同的ID返回相同的实体实例。这意味着如果从同一会话中检索到两个person1 == person1实例,则Person应始终为true。这也会带来关系,因此如果两个休假请求具有相同的人员ID,vacationRequest1.Person == vacationRequest2.Person也将在同一会话中成立。

这意味着你可以完全摆脱PersonComparer,除非你通过缓存混合来自多个会话的实体。

答案 2 :(得分:0)

对于初学者来说,它无法在你的数据库中执行代码。

这里有关于如何解决这个问题的建议

var peopleIds= people.Select(x=>x.Id);
Session.Query<VacationRequestDate>()
    .Where(r => peopleIds.Contains(r.VacationRequest.PeopleId)).ToList()
    .Where(x=>people.Contains(r.VacationRequest,new         
     PersonComparer()).Select(r=>r.VacationRequest).ToList()

如果您认为这不是您想要做的话,那么我建议您尝试使用Criteria查询或HQL,您可以从数据库中获得您想要的内容。

您也可以按如下方式使用比较器。我想让我的通用。 您也可以进行字符串比较,并在此处添加忽略大小写等逻辑。

public class ComparerByIntId<T> : IEqualityComparer<T>
    where T : class, IIntegerIdentifiable
{
    public bool Equals(T x, T y)
    {
        if (x == null && y == null)
            return true;

        if (x == null || y == null)
            return false;

        return x.Id == y.Id;
    }

    public int GetHashCode(T obj)
    {
        return base.GetHashCode();
    }
}

现在,当您运行查询时,它将如下所示:

Session.Query<VacationRequestDate>()
   .Where(r => people
   .Contains(r.VacationRequest.Person, new ComparerByIntId<Person>()))
   .Select(r=>r.VacationRequest)
   .ToList();

希望有所帮助