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

时间:2018-04-20 07:07:13

标签: c# entity-framework linq

我想在下面的模型的最后一条记录上执行条件:

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

查询:

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

在这里,我希望获得status = 1 and all jobs are recurring的TestPart的ID,但这应该只考虑checking last record of test part

但我无法在上述查询中选择上一个TestPart的ID。

更新:

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

所以这里我想基于TestId筛选出数据,然后选择该特定TEST的最后一条记录,然后检查所有作业类型是否为最后选择的TestPart id重复出现,即上面的情况TestPartId = 4。

3 个答案:

答案 0 :(得分:3)

解释有点支离破碎。为了确保我正在回答正确的问题,这些是我的假设:

  • 一个Test有许多TestPart个孩子。
  • 您想要给定测试的最后TestPart ,而不仅仅是表格的最后一个条目(无论测试ID)。
  • 您正在尝试确定最后一项是否符合条件,从而使代码的最终结果成为布尔值。

您需要在此处拆分数据检索数据验证步骤。

合并它们时,会得到不同的结果。您要求最后一个符合条件的项目。这意味着在10个项目(按时间顺序编号为1到10)的列表中,如果符合条件并且9和10不符合标准,则最终可能会获得项目 8

根据你的描述,我猜测那不是你想要的。您想要使用 10 项目(无论其是否符合条件,>检查此项目是否符合条件。

这样想:

  
      
  • 我想要最后一个名叫John的人进入这座建筑。
  •   
  • 我想知道进入大楼的最后一个人是否被命名为John。
  •   

您的代码正在尝试先执行此操作。但你真正想要的是第二个。

您的代码的正确版本:

//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包含您的答案。

修改 - 仅为完整性

有一些方法可以将它合并到一个查询中,但这会使代码容易被误解。

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

这会给你相同的结果。它依赖于“只有一个项目在列表上调用Any()的”技巧“。

虽然技术上正确,但我觉得这个版本不必要地复杂,可读性差,而且更容易被开发人员误解。

答案 1 :(得分:2)

.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;

答案 2 :(得分:1)

我认为适当的做法是将其分解为步骤。我确实喜欢像下一个人那样的大型LINQ语句,但只有当它优雅地代表了所需的逻辑时。在这种情况下,您需要获取记录,检查其状态并返回其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;

相关:Writing ROC (Really Obvious Code)