【问题标题】:Query for entities which are not joined with some other certain entities查询未与其他某些特定实体连接的实体
【发布时间】:2012-08-22 06:58:13
【问题描述】:

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

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. 退出应用程序

这似乎是一个非常微不足道的问题,但我在执行第二步时遇到了问题。我尝试了各种查询,但有些规则总是让我停下来。

以下是我在执行第 1 步时必须遵守的一些规则:

  • 我不允许修改 User 类或 User SQL 表
  • 如果有助于解决问题,我可能会修改任务类和表
  • 如果有帮助,我可能会添加新表或存储过程
  • 我必须以尽可能与 NHibernate 和 LINQ 兼容的方式实现它
  • 可能还存在一些不与任何用户对象关联的任务(调度程序将忽略这些任务,但在设计 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. 在第一次迭代中,查询应该返回用户实体 UserId=1 因为当前会话中没有任务 还没有用户
  3. 现在调度器创建一个 UserId=1 的新任务, SchedulerSessionUid=76ea57fa-8c89-4c05-9ca2-a450b1f8a032。

在下一次迭代中,调度程序应该获得一个 UserId=2 的用户。再次插入一个新任务,UserId=2,SchedulerSessionUid=76ea57fa-8c89-4c05-9ca2-a450b1f8a03。 在下一次迭代中,调度程序应该没有用户,所以它退出。

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

【问题讨论】:

    标签: sql linq nhibernate


    【解决方案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
    }
    

    而不是每次都访问数据库?

    【讨论】:

    • 谢谢,它看起来很有希望,但它也应该考虑到 SchedulerSessionUid。可能存在来自先前会话的有效用户任务,在当前调度程序应用程序会话中应忽略它们。
    • 更接近你想要的吗?做不到这一点,足以帮助您实现它吗?
    • 我明天试试。希望 NHibernate 不会搞砸(我听说人们偶然发现了 NHibernate LINQ 提供程序的一些问题;仍然有一些不受支持的功能和表达式组合)。
    • 祝你好运。那里我无能为力,我 ken linq,但不是很休眠。
    • 成功了!只是一点点修复: Users.Where(u => !Tasks.Any(t => t.UserId == u.UserId && t.SchedulerSessionUid == curSession)).FirstOrDefault();在 !Tasks.Any 之前需要 u =>。 NHibernate 用“not (exists(select ...”) 做了一个不错的子查询
    猜你喜欢
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 2015-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多