查询未与某些其他特定实体连接的实体

时间:2012-08-27 18:58:37

标签: sql linq nhibernate

我正在尝试实现自定义任务调度程序系统。 我有一个以下(简化的)实体模型:

class User
{
    public virtual long UserId { get; set; }
    public virtual string Name { get; set; }
}

class Task
{
    public virtual long TaskId { get; set; }
    public virtual long? UserId { get; set; }
    public virtual string TaskName { get; set; }
    public virtual Guid SchedulerSessionUid { get; set; }
}

目前,相应的SQL表是直接的,字段映射与上面的类中显示的完全相同。

调度程序是C#Windows控制台应用程序。它每天运行一次。 它应该以下列方式工作(简化):

  1. 为当前会话生成Guid
  2. 尝试选择下一个用户实体,该实体尚未在当前的调度程序会话中安排任务(Guid比较);如果没有找到这样的用户,请转到步骤5.
  3. 为在步骤2中选择的用户添加新任务。
  4. 转到第2步。
  5. 退出申请
  6. 这似乎是一个非常微不足道的问题,但我在实施第二步时遇到了问题。我尝试过各种各样的查询,但有一些规则总是阻止我。

    以下是我在实施步骤1时必须遵守的一些规则:

    • 我不允许修改User类或User SQL表
    • 我可以修改Task类和表,如果它有助于解决问题
    • 我可以添加新表或存储过程,如果有帮助
    • 我必须以尽可能与NHibernate和LINQ兼容的方式实现它
    • 可能还存在一些与任何User对象无关的任务(调度程序将忽略这些任务,但在设计SQL / LINQ查询和NHibernate映射时仍需记住这一点。)

    以下是一些现实世界的例子,它应该如何运作。

    Users
    -----------------
    UserId    Name
    -----------------
    1         First
    2         Second
    
    
    Tasks
    --------------------------------------------------------
    TaskId    UserId    SchedulerSessionUid 
    --------------------------------------------------------
    1         NULL      6d8e48d0-4e92-477e-82fa-cd957e7dc201    
    2         1         d213cfc8-23d6-49fb-b4e3-9ff3b60af6c4
    3         1         9ee042df-88a7-447e-adbd-e7551ed50ae5
    

    1.当调度程序运行时,它会生成当前会话ID = 76ea57fa-8c89-4c05-9ca2-a450b1f8a032。

    1. 现在它应该向NHibernate LINQ发出神奇的LINQ查询 提供者获取用户实体
    2. 在第一次迭代中,查询应返回User实体 UserId = 1,因为当前会话中没有任务 用户
    3. 现在,调度程序使用UserId = 1创建一个新任务, SchedulerSessionUid = 76ea57fa-8c89-4c05-9ca2-a450b1f8a032。
    4. 在下一次迭代中,Scheduler应该获得UserId = 2的User。同样,使用UserId = 2,SchedulerSessionUid = 76ea57fa-8c89-4c05-9ca2-a450b1f8a03插入新任务。 在下一次迭代中,Scheduler应该没有用户,因此退出。

      我可以使用哪些LINQ查询来获取第2步的用户?我需要对SQL模式和实体模型进行哪些更改?

1 个答案:

答案 0 :(得分:1)

如果我现在正确地关注您,您需要获得一个(仅一个)用户,其中没有具有给定会话ID的任务。我是对的吗?

Users.Where(u => !Tasks.Any(t = > t.UserId == u.UserId && t.SchedulerSessionUid == curSession)).FirstOrDefault()

编辑:

由于你正在做几次旋转,你或许可以更快地做:

foreach(var user toDealWith Users.Where(u => !Tasks.Any(t = > t.UserId == u.UserId && t.SchedulerSessionUid == curSession)))
{
  //do stuff
}

而不是每次都持续点击数据库?