实体框架核心-不在



我试图在EF Core中复制SQL语句,但似乎找不到一种方法来做到这一点,设置场景,我有以下表结构

槽→SlotInstance→SlotInstanceUser(一个Slot可以有多个SlotInstance,一个SlotInstance可以有多个SlotInstanceUsers)

当用户注册一个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是最后一个,变量(别名)是强制性的,与SQLNOT 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       
};

(这实际上转换为SQLNOT EXISTS,但这不是必需的)。

如果你不需要投影,但只是槽实例(槽信息),用户没有注册,那么它将是简单的

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

最新更新