0

我有一个引用自身的类,如下所示:

public class Person
{
    int Id { get; set; }
    string Name { get; set; }
    DateTime CreatedOn { get; set; }

    Person Parent { get; set; }
    ICollection<Person> Children { get; set; }
}

我需要的是一个 Linq 查询,它将返回一个列表,该列表仅包含那些有孩子的记录的最新记录(基于“CreatedOn”),或者那些没有孩子的父母本身。查询还需要对整个“家庭”应用一些过滤器。例如,如果我按名称“John”过滤,并且只有父母的名字是“John”,我仍然需要检索它最近的孩子。

任何帮助,将不胜感激。

4

4 回答 4

2

你可以这样做:

var results = db.Persons.Where(p => p.Name == "John")
                        .Select(p => p.Children.OrderByDescending(c => c.CreadedOn).FirstOrDefault() ?? p);

或者,如果您更喜欢查询语法

var results = 
    from p in db.Persons
    where p.Name == "John"
    select(p => p.Children.OrderByDescending(c => c.CreadedOn).FirstOrDefault() ?? p);

生成的 sql 将如下所示:

SELECT 
    (CASE 
        WHEN NOT (EXISTS(
            SELECT TOP (1) NULL AS [EMPTY]
            FROM [Person] AS [t2]
            WHERE [t2].[ParentId] = [t0].[Id]
            ORDER BY [t2].[Id] DESC
            )) THEN 1
        WHEN NOT NOT (EXISTS(
            SELECT TOP (1) NULL AS [EMPTY]
            FROM [Person] AS [t2]
            WHERE [t2].[ParentId] = [t0].[Id]
            ORDER BY [t2].[Id] DESC
            )) THEN 0
        ELSE NULL
     END) AS [value], [t0].[Id], [t0].[ParentId], [t0].[Name], [t0].[CreatedOn]
FROM [Parent] AS [t0]
WHERE [t0].[Name] = @p0
GO
于 2013-04-03T15:30:52.787 回答
1

不确定使用 Linq-To-Entities,使用 Linq-To-Objects 这应该可以工作:

var lastChildOfJohn = persons.Where(p => p.Name == "John" && p.Children.Any())
    .SelectMany(p => p.Children)
    .OrderByDescending(p => p.CreatedOn)
    .FirstOrDefault(); 
于 2013-04-03T15:33:41.477 回答
0

您可能应该使用Stack对象,因为它们使用 LIFO(后进先出基础)。

这是 MSDN 的链接:-

http://msdn.microsoft.com/en-us/library/system.collections.stack.aspx

这对我来说,正是你想要做的。

如果您使用 Stack.Peek 方法,它将自动返回放置在堆栈上的最后一个对象。

您还可以使用 Pop 返回最新的对象,然后将其从堆栈中删除。

Peek 返回堆栈顶部的对象而不删除它。

Pop 移除并返回堆栈顶部的对象。

于 2013-04-03T15:51:09.940 回答
0

好吧,经过大量的摸索和反复试验,这是我提出的查询(为了便于阅读,分为 3 行):

var query = db.People.AsQueryable();
query = !string.IsNullOrEmpty(name) ? query.Where(x => x.Name.Contains(name) || x.Ocorrencias.Any(y => y.Name.Contains(name))) : query;
query = query.Select(p => (p.Children.Count == 0 && p.Parent == null) ? p : p.Children.OrderByDescending(c => c.CreatedOn).FirstOrDefault()).Where(x => x != null);

这将返回我需要的内容:将过滤器应用于父级和子级的对象列表(如果有的话)。如果有孩子,只返回最近的一个。我不得不把“Where x != null”放在最后,以过滤掉“FirstOrDefault”返回的空对象。

我打算将 pswg 和 Tim 的评论标记为答案,因为他们让我走上了正确的道路来解决这个问题,但显然我只能将一条评论标记为答案。谢谢您的帮助!

于 2013-04-04T13:41:06.587 回答