c# - Entity Framework 核心 - 不在

标签 c# sql-server entity-framework-core razor-pages

我正在尝试在 EF Core 中复制 SQL 语句,但似乎找不到方法来实现,为了设置场景,我有以下表结构

插槽 -> SlotInstance -> SlotInstanceUser (一个Slot可以有多个SlotInstance,一个SlotInstance可以有多个SlotInstanceUser)

当用户注册 SlotInstance 时,会在 SlotInstanceUsers 中创建一条记录,存储 SlotInstanceId 和 UserId - 那里一切都很好。

我可以编写 SQL 来获取用户尚未注册的插槽实例列表,例如

    SELECT
        S.StartDate, S.EndDate, S.StartTime, S.EndTime, S.DayOfWeek,
        SI.Date
    FROM
        Slot S WITH (NOLOCK)
    INNER JOIN
        SlotInstance SI WITH (NOLOCK) ON S.Id = SI.SlotId
    WHERE
        SI.ID not in (  
                        SELECT 
                            SlotInstanceId 
                        FROM 
                            SlotInstanceUser SIU WITH (NOLOCK) 
                        WHERE 
                            SIU.UserId = @UserID
                    )   
    ORDER BY
        SI.Date

但我似乎无法在 EF core 中复制它 - 我错过了什么?

最佳答案

您可以像编写 SQL 查询一样编写 LINQ 查询。请记住,在 LINQ 中,select 是最后一个,变量(别名)是必需的,而 SQL NOT IN 的等效项是 !Contains。例如

var query =
from s in db.Slots
join si in db.SlotInstances on s.Id equals si.SlotId
where !(from siu in db.SlotInstanceUsers
        where siu.UserId == userId)
        select siu.SlotInstanceId).Contains(si.Id)
orderby si.Date
select new
{
    s.StartDate, s.EndDate, s.StartTime, s.EndTime, s.DayOfWeek,
    si.Date       
};

但在 EF Core 中,您有更多选项,特别是对于联接,因为通常关系(和关联的联接)是用导航属性封装的。因此,您用 EF Core/C# 术语描述的模型类似于

public class Slot
{
    public int Id { get; set; }
    // Other properties...
    public ICollection<SlotInstance> SlotInstances { get; set; }
}

public class SlotInstance
{
    public int Id { get; set; }
    // Other properties...
    public Slot Slot { get; set; }
    public ICollection<SlotInstanceUser> SlotInstanceUsers { get; set; }
}

public class SlotInstanceUser
{
    public int Id { get; set; }
    // Other properties...
    public SlotInstance SlotInstance { get; set; }
}

查询就像这样

var query =
from s in db.Slots
from si in s.SlotInstances
where !si.SlotInstanceUsers.Any(siu => siu.UserId == userId)
orderby si.Date
select new
{
    s.StartDate, s.EndDate, s.StartTime, s.EndTime, s.DayOfWeek,
    si.Date       
};

(这实际上翻译为 SQL NOT EXISTS,但这不是必需的)。

如果您不需要投影,而只是需要用户尚未注册的插槽实例(带有插槽信息),那么就很简单

var query = db.SlotInstances
    .Include(si => si.Slot)
    .Where(si => !si.SlotInstanceUsers.Any(siu => siu.UserId == userId))

关于c# - Entity Framework 核心 - 不在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71979823/

相关文章:

sql-server - 检查记录是否存在,如果是,则“更新”,如果不是,则“插入”

sql-server - 如何在SQL Server中获取子字符串?

c# - 如何使用 EF Core 将 JSON 存储在实体字段中?

postgresql - 使用 Entity Framework Core 时自动增量值在 PostgreSQL 中不起作用

Linux/OSX 中的 C# GUI

c# - 应用黑白不透明度后生成颜色

sql - 在选择查询中使用相对日期

sql-server - Entity Framework 扩展递归查询

c# - 失去焦点后如何保持 NumericUpDown 的无效值?

c# - 如何从 dapper 返回 "Select * from table"的 Task<List<Model>> ,而不必再次查询第一个查询的结果 id?