简体   繁体   English

在表的最后一条记录上执行条件并获取该记录的ID

[英]Perform condition on last record of table and get id of that record

I want to perform condition on last record of my below model : 我想对以下模型的最后一条记录执行条件:

 public partial class TestPart
    {
       public int Id { get; set; }
       public int TestId { get; set; }
       public int Status { get; set; }
       public virtual ICollection<Job> Jobs { get; set; }
    }

Query : 查询:

var query = context.TestPart.OrderByDescending(tp=>tp.Id)
                                                .Take(1)
                                                .Where(tp => tp.TestId == 100 &&
                                                 tp.Status == 1 &&
                                                 tp.Jobs.All(j => j.Type == "Recurring")

Here I want to get Id of TestPart whose status = 1 and all jobs are recurring but this should only consider checking last record of test part 在这里,我想获取status = 1 and all jobs are recurring的TestPart的ID,但这仅应考虑checking last record of test part

But I am unable to select Id of last TestPart in above query. 但是我无法在上面的查询中选择最后一个TestPart的ID。

Update : 更新:

Id    TestId       Status     
1     100          1
2     100          2
3     100          0
4     100          1
5     101          1

so here I want to filter out data based on TestId and then select last record for that specific TEST and then check out whether all job types are recurring for that last selected TestPart id ie in above case TestPartId=4. 所以在这里我想根据TestId筛选出数据,然后为该特定TEST选择最后一条记录,然后检查该最后选择的TestPart ID是否重复所有作业类型,即在上述情况下为TestPartId = 4。

The explanation is a bit fragmented. 解释有点零散。 In order to make sure that I'm answering to the right problem, these are my assumptions: 为了确保我在回答正确的问题,以下是我的假设:

  • One Test has many TestPart children. 一个Test有许多TestPart子级。
  • You want the last TestPart of a given test , not just the last entry of the table (regardless of test id). 您需要给定测试的最后一个TestPart ,而不仅仅是表的最后一个条目(无论测试ID是什么)。
  • You're trying to ascertain if this last item fits the criteria, thus making the end result of your code a boolean value. 您正在尝试确定最后一项是否符合条件,从而使代码的最终结果为布尔值。

You need to split the data retrieval and data validation steps here. 您需要在此处拆分数据检索数据验证步骤。

When you merge them, you get different results. 合并它们时,会得到不同的结果。 You ask for the last item that fits the criteria. 您要求提供符合条件的最后一项。 This means that in a list of 10 items (numbered 1 through 10 chronologically) you might end up getting item 8 if it fits the criteria and 9 and 10 do not fit the criteria. 这意味着,在10个项目的列表中(按时间顺序编号1到10),如果符合条件而第9项和第10项不符合条件,则可能最终得到第8项。

From your description, I surmise that's not what you want. 根据您的描述,我想这不是您想要的。 You want to take item 10 (regardless of whether it fits the criteria, and only then check if this item fits the criteria or not. 您想取第10项(无论它是否符合条件,然后检查该项目是否符合条件。

Think of it this way: 这样想:

  • I want the last person named John who entered this building. 我要最后一个叫约翰的人进入这座大楼。
  • I want to see if the last person who entered the building is named John. 我想看看最后进入大楼的人是否叫约翰。

Your code is trying to do the first. 您的代码正在尝试执行第一个操作。 But what you really want to do is the second. 但是,您真正想做的是第二个。

The correct version of your code: 您的代码的正确版本:

//Get the last testpart of the test.
TestPart item = context.TestPart
                       .Include(tp => tp.Jobs)  //possibly optional dependent on lazy/eager loading.
                       .OrderByDescending(tp=>tp.Id)
                       .First(tp => tp.TestId == 100);

//Check if this item fits the criteria
bool isValid = 
          item.Status == 1 
          && item.Jobs.All(j => j.Type == "Recurring");

isValid contains your answer. isValid包含您的答案。


Edit - just for completeness 编辑-仅出于完整性

There are ways to merge this into one query, but this makes the code easily prone to misinterpretation. 有多种方法可以将其合并为一个查询,但是这会使代码容易产生误解。

bool isLastItemValid = context.TestPart
                          .Where(tp => tp.TestId == 100)
                          .OrderByDescending(tp => tp.Id)
                          .Take(1)
                          .Any(tp =>
                                   tp.Status == 1 
                                   && tp.Jobs.All(j => j.Type == "Recurring");

This gives you the same result. 这给您相同的结果。 It relies on the "trick" that calling Any() on a list with only one item really just evaluates the one item. 它依赖于“技巧”,即只有一个项目的列表上调用Any()实际上只是评估一个项目。

While technically correct, I find this version unnecessarily complicated, less readable, and more prone to developer misinterpretation. 尽管从技术上讲是正确的,但我发现此版本不必要地复杂,可读性差,并且更容易被开发人员误解。

Replace .Take(1).Where() with FirstOrDefault() FirstOrDefault()替换.Take(1).Where() FirstOrDefault()

TestPart item = context.TestPart.OrderByDescending(tp => tp.Id)
                       .FirstOrDefault(tp => tp.TestId == 100 &&
                                             tp.Status == 1 &&
                                             tp.Jobs.All(j => j.Type == "Recurring");
int result = item.Id;

I think the appropriate thing to do is break it into steps. 我认为适当的做法是将其分解为若干步骤。 I do love a big LINQ statement like the next guy, but only when it elegantly represents the required logic. 我确实喜欢下一个家伙那样的大型LINQ语句,但是仅当它优雅地表示所需的逻辑时。 In this case you're to get a record, check its status, and return its ID, so why not express that in ROC? 在这种情况下,您将获得记录,检查其状态并返回其ID,那么为什么不在ROC中表达呢?

var lastPart = context.TestPart.OrderByDescending(tp=>tp.Id)
                      .First();

bool match =  (lastPart.TestId == 100 &&
               lastPart.Status == 1 &&
               lastPart.Jobs.All( j => j.Type == "Recurring"));

if (match) return lastPart.Id;

Relevant: Writing ROC (Really Obvious Code) . 相关: 编写ROC(确实很明显的代码)

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

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