简体   繁体   English

复杂的顺序问题(实体框架)

[英]Complex orderby question (entity framework)

Ok, so I will start by saying that I am new to all this stuff, and doing my best to work on this project. 好的,所以我首先要说的是我对这些东西都是新手,并且尽我所能来完成这个项目。 I have an employee object, that contains a supervisor field. 我有一个员工对象,其中包含一个主管字段。 When someone enters a search on my page, a datagrid displays employees whose name match the search. 当有人在我的页面上输入搜索时,数据网格会显示其名称与搜索匹配的员工。 But, I need it to display all employees that report to them and a third tier of employees that report to the original employee's underlings. 但是,我需要它来显示向他们报告的所有员工以及向原始员工的下属报告的第三层员工。 I only need three tiers. 我只需要三层。 To make this easier, employees only come in 3 ranks, so if rank==3, that employee is not in charge of others. 为了使这更容易,员工只有三个等级,所以如果等级= = 3,该员工不负责其他人。 I imagine the best method of retrieving all these employees from my employee table would be something like 我想从我的员工表中检索所有这些员工的最佳方法就是这样的

from employee in context.employees
where employee.name == search || employee.boss.name == search || 
employee.boss.boss.name == search

But I am not sure how to make the orderby appear the way I want to. 但我不知道如何让秩序以我想要的方式出现。 I need it to display in tiers. 我需要它以层级显示。 So, it will look like: Big Boss- Boss- underling- underling- Boss- underling- Boss- Boss- Big Boss- 所以,它看起来像:Big Boss- Boss- underling-underling- Boss- underling- Boss- Boss- Big Boss-

Like I said, there might be an easier way to approach this whole issue, and if there is, I am all ears. 就像我说的那样,可能有一种更简单的方法可以解决这个问题,如果有的话,我会全力以赴。 Any advice you can give would be HIGHLY appreciated. 您可以给予任何建议,我们将非常感激。

This seems a difficult requirement to solve using any particular ORM framework, at least not in one easy step. 这似乎是使用任何特定ORM框架解决的一个困难的要求,至少不是一个简单的步骤。 A multi-step process is likely to be necessary. 可能需要多步骤过程。

Something roughly similar can be accomplished via an approach to iterate through the search results and finding their children (and children's children), and flattening the hierarchy into a single list. 大致相似的东西可以通过迭代搜索结果并找到他们的孩子(和孩子的孩子),并将层次结构扁平化为单个列表的方法来实现。 An example implementation here, this one done using a plain in-memory list: 这里有一个示例实现,这个实现使用简单的内存列表:

class Employee
{
    public int Id { get; private set; }
    public int? BossId { get; private set; }
    public string Name { get; private set; }

    public Employee(int id, int? bossId, string name)
    {
        Id = id;
        BossId = bossId;
        Name = name;
    }
}

Sample data: 样本数据:

List<Employee> employees = new List<Employee>();
employees.Add(new Employee(1, null, "Tom Smith"));
employees.Add(new Employee(2, null, "Susan Jones"));
employees.Add(new Employee(3, 1, "Sally Davis"));
employees.Add(new Employee(4, 1, "Robert Roberts"));
employees.Add(new Employee(5, 3, "John Smith"));
employees.Add(new Employee(6, 2, "Tonya Little"));
employees.Add(new Employee(7, 3, "Ty Bell"));
employees.Add(new Employee(8, 4, "Helen Andrews"));
employees.Add(new Employee(9, 2, "Matt Huang"));
employees.Add(new Employee(10, 6, "Lisa Wilson"));

Process: 处理:

string searchTerm = "Smith";

var searchResults = employees.Where(e => e.Name.Contains(searchTerm));

List<Employee> outputList = new List<Employee>();

Action<IEnumerable<Employee>, List<Employee>> findUnderlings = null;
findUnderlings = (input, list) =>
{
    foreach (Employee employee in input)
    {
        list.Add(employee);
        var underlings = employees.Where(e => e.BossId == employee.Id);
        findUnderlings(underlings, list);
    }
};

findUnderlings(searchResults, outputList);

Show output: 显示输出:

foreach (Employee employee in outputList)
{
    Console.WriteLine("{0}\t{1}\t{2}", employee.Id, employee.Name, employee.BossId);
}

Results: 结果:

1       Tom Smith
3       Sally Davis     1
5       John Smith      3
7       Ty Bell 3
4       Robert Roberts  1
8       Helen Andrews   4
5       John Smith      3

And you can see it follows the top result, underling, underling's underlings, next result, any underlings, etc. It works for any number of tiers. 你可以看到它遵循最高结果,下属,下属的下属,下一个结果,任何下属等。它适用于任意数量的层。

I am not sure how that can be accomplished in an "order by" within Linq or even regular SQL, but that could only mean I'm not smart enough to do it rather than it just isn't possible. 我不确定如何在Linq中的“order by”或甚至常规SQL中实现这一点,但这只能意味着我不够聪明,而不是只是不可能。

Hey, I thought I would post the way I ended up solving this issue, in case it might come in handy for someone else. 嘿,我以为我会发布我最终解决这个问题的方式,以防它可能派上用场。

var list = productQuery.ToList();
var productList = Functions.sortResultsList(list);




public static List<SolutionsModel.Version> 
   sortResultsList(List<SolutionsModel.Version> list)
{
    var productList = new List<SolutionsModel.Version>();

    int total = list.Count();
    int solutions = 0;
    int objects = 0;

    for (int length = 0; length < list.Count(); length++)
    {
        if (list[length].Product.TypeID == 1)
        {
            ++solutions;
        }
        else if (list[length].Product.TypeID == 2)
        {
            ++objects;
        }
    }

    //These nested for-loops create a list that is 
    //correctly ordered to fit correctly into the grid. 
    //Perhaps consider more efficient improvision at a later time.

    //These for loops can't be used if there are not any solutions 
    //in the results
    if (solutions != 0)
    {
        for (int x = 0; x < list.Count; x++)
        {
            if (list[x].Product.TypeID == 1)
            {
                productList.Add(list[x]);
                for (int y = 0; y < list.Count; y++)
                {
                    if (list[y].Product.TypeID != 1)
                    {
                        if (list[y].Product.Product2.ID == list[x].Product.ID && list[y].VersionNumber == list[x].VersionNumber)
                        {
                            productList.Add(list[y]);
                            for (int j = 0; j < list.Count; j++)
                            {
                                if (list[j].Product.TypeID == 3)
                                {
                                    if (list[j].Product.Product2.ID == list[y].Product.ID && list[j].VersionNumber == list[y].VersionNumber)
                                    {
                                        productList.Add(list[j]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    //This can't be used if the results do not contain any objects.
    if (objects != 0 && productList.Count != total)
    {
        for (int y = 0; y < list.Count; y++)
        {
            if (list[y].Product.TypeID == 2)
            {
                productList.Add(list[y]);
                for (int j = 0; j < list.Count; j++)
                {
                    if (list[j].Product.TypeID == 3)
                    {
                        if (list[j].Product.Product2.ID == list[y].productID && list[j].VersionNumber == list[y].VersionNumber)
                        {
                            productList.Add(list[j]);
                        }
                    }
                }
            }
        }

    }

    //If the results contain only modules, no sorting is required and the original list can be used.
    if (productList.Count != total)
    {
          return list;
    }

    return productList;
}

I don't know much of LINQ. 我对LINQ知之甚少。 But, why can't this be done using a stored procedure, which can be referred by your EF Model? 但是,为什么不能使用存储过程来完成,这可以由您的EF模型引用?

I think, one shouldn't use LINQ for everything :) 我认为,不应该使用LINQ的一切:)

EDIT: The reason I say that use of stored procedure makes sense is because EF will have to generate SQL query to do what you want & what you want to do, can be better expressed & controlled in SQL. 编辑:我说使用存储过程是有道理的原因是因为EF必须生成SQL查询来做你想做的事情和你想做什么,可以在SQL中更好地表达和控制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM