Cod*_*erK 3 c# sql-server entity-framework-core razor-pages
我正在尝试在 EF Core 中复制 SQL 语句,但似乎找不到方法来实现,为了设置场景,我有以下表结构
Slot -> 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
Run Code Online (Sandbox Code Playgroud)
但我似乎无法在 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
};
Run Code Online (Sandbox Code Playgroud)
但在 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; }
}
Run Code Online (Sandbox Code Playgroud)
查询就像
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
};
Run Code Online (Sandbox Code Playgroud)
(这实际上转换为 SQL NOT EXISTS,但这不是必需的)。
如果您不需要投影,而只是用户尚未注册的插槽实例(带有插槽信息),那么它就很简单
var query = db.SlotInstances
.Include(si => si.Slot)
.Where(si => !si.SlotInstanceUsers.Any(siu => siu.UserId == userId))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2572 次 |
| 最近记录: |