简体   繁体   English

实体框架 ASP.NET MVC:在多对多场景中从相关表中查找最后一条记录

[英]Entity Framework ASP.NET MVC : find last record from related table in a many to many scenario

I just finished a solution but the client requested to implement many filters on the results.我刚刚完成了一个解决方案,但客户要求对结果实施许多过滤器。

In this case the client needs to filter all the orders that are in what ever status they choose.在这种情况下,客户需要过滤所有处于他们选择的任何状态的订单。

In summary this is a sample of the tables I'm having problems to query and filter with Entity Framework and lambda syntax.总之,这是我在使用 Entity Framework 和 lambda 语法查询和过滤时遇到问题的表示例。

在此处输入图像描述

  1. Each complaint has a description and insert date.每个投诉都有描述和插入日期。
  2. Users can change the status of the complaint.用户可以更改投诉的状态。 That change is recorded in the intermediate table ComplaintStatus该更改记录在中间表ComplaintStatus

The Status table has all the possible status and the records are "On Hold", "Pending Repair", "In Delivery", etc Status表包含所有可能的状态,记录为“暂停”、“等待修复”、“交货中”等

As you can see, this is many to many relation as we can have many complaints in many statuses.正如你所看到的,这是多对多的关系,因为我们可以在许多状态下有很多投诉。

More over, a complaint can change to status id 1, later to status id 2 and return back to status 1 and all is recorder historically in the ComplaintStatus intermediate table avoiding deletions.此外,投诉可以更改为状态 id 1,稍后更改为状态 id 2 并返回到状态 1,并且历史上所有内容都记录在ComplaintStatus中间表中,避免删除。

So, for the filter, I need to find the last Status of a Complaint .因此,对于过滤器,我需要找到最后一个Status Complaint

This is part of my code:这是我的代码的一部分:

var query = dbContext.Complaint                         // To get the Complaints table 
                     .Include(c => c.ComplaintStatus)   // To get the ComplaintStatus table
                     .Include(s => d.ComplaintStatus.Select(st => st.Status))       // To get the Status table
                     .AsQueryable();

var complaintId = 0;
var statusId = 0; 

// As per my research we need to check if the filters variables has values or return all 
// if we do not have filters in place.
// For this, I check if any filter has a value different than 0 and also re-check in the where 
// clause if I need to filter by that specific item

if (complaintId || statusId)
{
    query = query.Where(x => (
                // This returns perfectly                   
                (complaintId && x.Id.Equals(complaintId))      

                // This is where I'm totally stuck with no clue on how to search for the last Complaint Status equal to the designated statusId

                || (statusId && ((x.Complaint.GroupBy(c => c.id)
                                    .Select(co => co.OrderByDescending(co => co.InsertDate).FirstOrDefault()) )
                                    .Any(s => s.StatusId.Equals(statusId))
                                )
                    )
}

// Finally I fire the DB request 
var response = query.ToListAsync();

EF is complaining that I cannot perform and orderby inside a where EF 抱怨我无法在 where 内执行和 orderby

One possible solution I found around is to use a delegate inside the where clause Subquery in Where Clause of LINQ statement我发现的一种可能的解决方案是在 LINQ 语句的 Where 子句中的 where 子句子查询中使用委托

Is there any versed EF developer that can help achieve this?是否有任何精通 EF 开发人员可以帮助实现这一目标?

Cheers,干杯,

I just come across a solution for this using the suggestion from a colleague.我只是根据同事的建议遇到了一个解决方案。

Adding a column in the Table ComplaintStatus to mark if the status is the last one.在表 ComplaintStatus 中添加一列以标记状态是否为最后一个。 The new column name is Active of type bit and default value 1新列名是位类型的活动,默认值为 1

Each time a status change, 1st I search for all the previous status and change the Active column to 0. I also stamp the dateTime when this happen.每次状态更改时,我首先搜索所有以前的状态并将 Active 列更改为 0。我还会在发生这种情况时标记 dateTime。 2nd I insert the new status relation and as the default of the column is 1 this will be the only state that has the Active Mark.第二,我插入新的状态关系,因为列的默认值为 1,这将是唯一具有活动标记的 state。

This is the query to find the last state of a complaint:这是查找投诉的最后一个 state 的查询:

var query = dbContext.Complaint                         // To get the Complaints table 
                     .Include(c => c.ComplaintStatus)   // To get the ComplaintStatus table
                     .Include(s => d.ComplaintStatus.Select(st => st.Status))       // To get the Status table
                     .AsQueryable();

var complaintId = 0;
var statusId = 0; 

// As per my research we need to check if the filters variables has values or return all 
// if we do not have filters in place.
// For this, I check if any filter has a value different than 0 and also re-check in the where 
// clause if I need to filter by that specific item

if (complaintId || statusId)
{
    query = query.Where(x => (
                // This returns perfectly                   
                (complaintId && x.Id.Equals(complaintId))      

                // This is where I'm totally stuck with no clue on how to search for the last Complaint Status equal to the designated statusId

                || (statusId && x.Status.Any(y => (y.Status == statusId && y.Active == true)))
}

// Finally I fire the DB request 
var response = query.ToListAsync();

Please, comment if you know how to perform a select + orderBy inside a dynamic where clause as that will be super helpfull on this type of intricate search如果您知道如何在动态 where 子句中执行 select + orderBy,请发表评论,因为这对这种复杂的搜索非常有帮助

cheer欢呼

Well, well... just by luck I land on the solution of this query... Hope this help others stuck at same situation.好吧,好吧...只是运气好,我找到了这个查询的解决方案...希望这可以帮助其他人陷入同样的境地。

To find the last record of the intermediate table we can use the MAX verb and compare agains dates as follows:要查找中间表的最后一条记录,我们可以使用 MAX 动词并再次比较日期,如下所示:

if (complaintId || statusId)
{
    query = query.Where(x => (
                // This returns perfectly                   
                (complaintId && x.Id.Equals(complaintId))      

                // This is where I'm totally stuck with no clue on how to search for the last Complaint Status equal to the designated statusId

                || (statusId && ((x.Complaint.Any(y => (y.InsertDate == x.ComplaintStatus.Max(f => f.InsertDate))))
                                )
                    )
                ))
}

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

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