为什么不 nhibernate 支持“存在于列表中”句法?

发布于 2024-10-10 08:14:06 字数 789 浏览 2 评论 0原文

我有以下查询,它在 Nhibernate 3 LINQ 中失败并出现“不支持”异常。它与这个问题类似但是有人提出了这个问题一年多前,所以我确信答案已经过时了。

我的数据库表是:

  1. VacationRequest (id, personId)
  2. VacationRequestDate (id, VacationRequestId)
  3. Person (id, FirstName, LastName)

我的实体是:

  1. VacationRequest (Person, IList)
  2. VacationRequestDate (VacationRequest, Date)

这是获取“不支持”异常

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

是否有更好的方法来编写 Nhibernate 支持的方法?

供参考 。 .PersonComparer 只是比较 person.Id

i have the following query and its failing in Nhibernate 3 LINQ witha a "Non supported" exception. Its similar to this question but this question was asked over a year ago so i am positive that the answer is out of date.

My DB tables are:

  1. VacationRequest (id, personId)
  2. VacationRequestDate (id, vacationRequestId)
  3. Person (id, FirstName, LastName)

My Entities are:

  1. VacationRequest (Person, IList)
  2. VacationRequestDate (VacationRequest, Date)

Here is the query that is getting a "Non supported" Exception

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

is there a better way to write this that would be supported in Nhibernate?

fyi . .the PersonComparer just compared person.Id

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

再浓的妆也掩不了殇 2024-10-17 08:14:06

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

nhibernate cannot translate your new PersonComparer() you should change it.

雨落□心尘 2024-10-17 08:14:06

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

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

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

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

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

NHibernate does not understand the PersonComparer type, and thus cannot translate its usage to SQL.

Have you tried using the overload of Contains which does not accept a comparer? NHibernate should infer that you are comparing entity instances and properly use the ID in the SQL comparison (what else could it use?):

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

Also, keep in mind that within a single NHibernate session, the same entity instance is always returned for the same ID. This means that person1 == person1 should always be true if both Person instances were retrieved from the same session. This carries through relationships as well, so vacationRequest1.Person == vacationRequest2.Person will also be true within the same session if both vacation requests have the same person ID.

This means you can probably get rid of PersonComparer entirely unless you are mixing entities from multiple sessions through caching.

梦年海沫深 2024-10-17 08:14:06

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

好吧,这是我关于如何解决这个问题的建议,

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

希望有帮助

For starters it cant execute the code against that in your db.

Well here are my suggestions on how to go about this

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

If you think this isnt wha tyou want to do then I would suggest you try your hand at Criteria queries or HQL and you can get exactly what you want from the db.

You can also use your comparer as follows. I like to make mine generic.
You can make it string comparison too and you will add your logic of ignore case etc here.

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

Now when you run your query it will be as follows:

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

Hope that helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文