如何在 C# EF Core 中使用 join 子句中的条件编写 SQL 命令

Posted

技术标签:

【中文标题】如何在 C# EF Core 中使用 join 子句中的条件编写 SQL 命令【英文标题】:How to write a SQL command in C# EF Core with a condition in the join clause 【发布时间】:2021-11-20 02:32:36 【问题描述】:

我正在尝试在 C# EF Core 查询中翻译以下 SQL 命令。

SELECT u.firstname, c.name FROM notification AS n 
LEFT JOIN user AS u ON n.objectID=u.userID AND n.notificationType=0
LEFT JOIN conversation c ON n.objectID=c.conversationID AND n.notificationType=1;

所以基本上,我有 3 张桌子。 userconversation 表包含有关用户和对话的信息。 notification 表包含字段 notificationType,告诉它是哪种类型的通知:0 表示 user 通知,1 表示 对话 通知。通知表中的字段 objectID 包含一个 id。此字段中的 id 取决于 notificationType 中的值。如果值为 0,则 id 是用户 id。如果值为 1,则 id 为会话 id。因此,根据 notificationType 的值,我想加入不同的表。我目前能够执行所有命令,除了在每个 JOIN 命令的 ON 子句中添加 AND...

这种设计的想法是减少通知表的列数量。将来,会有更多的通知类型。那么如何在 EF Core 函数调用中翻译 SQL 请求?也许这个设计也很糟糕。我非常愿意接受任何建议。谢谢。

【问题讨论】:

您编写匿名类型的对象并在它们之间进行equals 连接。看看dotnettricks.com/learn/linq/… 【参考方案1】:

您可以在每个层次的表中使用泛型。这样您就可以生成正确的连接,只需使用导航属性。

public abstract class Notification
    public int NotificationType  get; set; 
    public int ParentId  get; set; 

public class Notification<T> where T:class
    public T Parent  get; set; 

public class User 
    public virtual ICollection<Notification<User>> Notification  get; set; 

public class Conversation 
    public virtual ICollection<Notification<Conversation>> Notification  get; set; 


// OnModelCreating

modelBuilder.Entity<Notification>()
    .HasDiscriminator(n => n.NotificationType)
        .HasValue<Notification<User>>(0)
        .HasValue<Notification<Conversation>>(1);

modelBuilder.Entity<User>()
    .HasMany(u => u.Notification)
    .WithOne(n => n.Parent)
    .HasForeignKey(n => n.ParentId);

modelBuilder.Entity<Conversation>()
    .HasMany(u => u.Notification)
    .WithOne(n => n.Parent)
    .HasForeignKey(n => n.ParentId);

尽管 EF Core 迁移可能会尝试创建无效的外键。如何在数据库中表示关系是一个单独的问题。

您还可以引入一个奇怪的递归接口。确保一切配置正确。

public interface IHaveNotifications<T> where T:class,IHaveNotifications<T>
    int Id  get; set; 
    ICollection<Notification<T>> Notification  get; set; 

但我会将其余的实现留给读者作为练习。

【讨论】:

以上是关于如何在 C# EF Core 中使用 join 子句中的条件编写 SQL 命令的主要内容,如果未能解决你的问题,请参考以下文章

使用 EF Core 保存附加实体时如何删除子实体

实战 EF(LINQ) 如何以子查询的形式来 Join

如何将带有 LEFT JOIN 的 SQL 转换为 EF CORE 3 LINQ

EF Core 中DbContext不会跟踪聚合方法和Join方法返回的结果

EF Core Inner join 改为 Left

如何使用 PredicateBuilder、EF Core 5 和 Postgresql 10+ 执行不区分大小写和重音的 LIKE(子字符串)查询?