Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有嵌套select的Linq查询_C#_.net_Linq_Entity Framework 6 - Fatal编程技术网

C# 具有嵌套select的Linq查询

C# 具有嵌套select的Linq查询,c#,.net,linq,entity-framework-6,C#,.net,Linq,Entity Framework 6,试图找出在linq语句中表达以下SQL的正确方法,但一无所获 select messageid, comment from Message where isactive = 1 and messageid in ( select messageid from org.Notification where NotificationTypeId = 7 and orguserid in ( select OrgUserId

试图找出在linq语句中表达以下SQL的正确方法,但一无所获

select messageid, comment 
from Message 
where isactive = 1 and messageid in 
(
    select messageid 
    from org.Notification 
    where NotificationTypeId = 7 and orguserid in 
    (
        select OrgUserId 
        from org.OrgUser
        where OrgId in 
        (
            select ChildOrgId from OrgRelation
            where ParentOrgId = 10001
        )
    )
    group by messageid
)

这与SQL Server中的情况一样,但我想在C E-F代码中使用此查询,而且我似乎在兜圈子。

如果需要使用in子句,则应使用该方法。

显然,通知对象具有messageId。多个通知对象可能具有相同的MessageId值

我想要Id等于 所有通知对象的子选择的MessageId值

首先,我将向您展示一个解决您的问题的LINQ查询,然后我将告诉您一些有关实体框架的信息,这些信息将使此类LINQ查询更易于理解和维护

直接解法 1选择应获取消息的通知:

3获取“MessageIDUsedByNotificationsUse”中Id为的所有活动邮件

TODO:如果需要:做一个大型LINQ语句

到目前为止,您还没有访问数据库。我只是改变了IQueryable中的表达式。让它成为一个大的LINQ语句不会大大提高性能,我怀疑它是否会提高可读性和可维护性

利用实体框架的可能性解决方案 消息和通知之间似乎存在一对多的关系:每个消息都有零个或多个通知,每个通知都只属于一条消息,使用外键MessageId

如果您坚持这样做,那么您的类的设计与下面的类似。强调一对多关系:

class Message
{
    public int Id {get; set;}

    // every Message has zero or more Notifications (one-to-many)
    public virtual ICollection<Notification> Notifications {get; set;}

    ... // other properties
}

class Notification
{
    public int Id {get; set;}

    // every Notifications belongs to exactly one Message using foreign key
    public int MessageId {get; set;}
    public virtual Message Message {get; set;}

    ... // other properties
}

class MyDbContext : DbContext
{
    public DbSet<Message> Messages {get; set;}
    public DbSet<Notification> Notifications {get; set;}
}
2现在,您可以直接选择属于这些通知的消息:

var result = notificationsToUse.Select(notification => notification.Message)
因为每个通知只属于一条消息,所以我确信没有重复的消息

继续:仅活动消息的MessageId和注释

    .Where(message => message.IsActive)
    .Select(message => new
    {
        MessageId = message.Id,
        Comment = message.Comment,
    });

我不确定通知、OrgUsers和OrgRelations之间的关系。如果您将类设计为表示适当的一对多或多对多关系,那么即使表达式1也会简单得多。

您可以将查询分解为3个不同的部分,如下所示-

首先过滤掉OrgUserID 使用FilteredorgUserId筛选出通知。 最后,通过查看FilteredNotification来过滤消息。 这应该行得通。请在您的终端尝试一次,并让我们知道这是否有帮助。

来自my,用于将SQL转换为LINQ到SQL:

将子选择转换为单独声明的变量。 按照LINQ子句顺序转换每个子句,将一元运算符和聚合运算符DISTINCT、TOP、MIN、MAX等转换为应用于整个LINQ查询的函数。 必须用SELECT new{…}替换SELECT字段以创建包含所有所需字段或表达式的匿名对象。 翻译成。包含而不是翻译成!。。。包含。 注意,您的SQL查询在应该使用DISTINCT时使用GROUP BY,然后应用配方规则:

var childOrgs = from or in OrgRelation where or.ParentOrgId == 1001 select or.ChildOrgId;
var orgUsers = from ou in OrgUser where childOrgs.Contains(ou.OrgId) select ou.OrgUserId;
var notificationMessages = (from n in Notification
                            where n.NotificationTypeId == 7 && orgUsers.Contains(n.orguserid)
                            select n.messageid).Distinct();
var ans = from m in Message
          where m.isactive == 1 && notificationMessages.Contains(m.messageid)
          select new { m.messageid, m.comment };

UH你绕圈子是什么意思?我没有看到任何循环引用..这些表没有关系吗?如果有关系,为什么不使用连接呢。如果没有任何关系,为什么需要他们提供的数据。另外,如果它变得复杂,把它放在一个存储过程中并调用它。请包括你尝试过的代码和你的想法。这也将告诉我们您是想要方法语法还是查询语法。@BagusTesa在圆圈中运行-它是一个表达式。从循环引用的角度来说,我并不是字面上的意思。抱歉给您带来任何困惑。@Pranetnadkar-是的。有一些关系。我想我也可以走加入的道路。我使用这个例子仅仅是因为它提供了SQL中所需的数据。这就是我目前采用的方法。它似乎工作得很好。然而,在ID列表变大的情况下,性能似乎会受到很大的影响。对此答案还有进一步的评论。在这个案子中我为自己工作,但最后我做了一些小的修改。在上面的示例中,每个序列都调用.ToList。在我的例子中,我删除它是为了推迟最后的执行。您好,先生,如果您仍然存在性能问题,那么为什么不使用存储过程呢?如果您需要在EF6中调用SPs的进一步帮助,请告知我们。
class Message
{
    public int Id {get; set;}

    // every Message has zero or more Notifications (one-to-many)
    public virtual ICollection<Notification> Notifications {get; set;}

    ... // other properties
}

class Notification
{
    public int Id {get; set;}

    // every Notifications belongs to exactly one Message using foreign key
    public int MessageId {get; set;}
    public virtual Message Message {get; set;}

    ... // other properties
}

class MyDbContext : DbContext
{
    public DbSet<Message> Messages {get; set;}
    public DbSet<Notification> Notifications {get; set;}
}
IQueryable<Notification> notificationsToUse = ... same as above
var result = notificationsToUse.Select(notification => notification.Message)
    .Where(message => message.IsActive)
    .Select(message => new
    {
        MessageId = message.Id,
        Comment = message.Comment,
    });
var filteredOrgUserIds = dc.OrgUsers.Where(u => dc.OrgRelations.Where(o 
    =>o.ParentOrgId == 10001).Select(d => 
    d.ChildOrgId).ToList().Contains(u.OrgId))
    .Select(uid => uid.OrgUserId)
    .Distinct()
    .ToList();
var filteredNotifications = dc.Notifications.Where(n => 
     n.NotificationTypeId == 7 && filteredOrgUserIds.Contains(n.OrgUserId))
     .Select(m => m.messageid)
     .Distinct()
     .ToList();
    m.isactive == 1 && filteredNotifications.Contains(m.messageid))
    .Select(m => new { message = m.messageid, comment = m.comment })
    .Distinct()
    .ToList();
var childOrgs = from or in OrgRelation where or.ParentOrgId == 1001 select or.ChildOrgId;
var orgUsers = from ou in OrgUser where childOrgs.Contains(ou.OrgId) select ou.OrgUserId;
var notificationMessages = (from n in Notification
                            where n.NotificationTypeId == 7 && orgUsers.Contains(n.orguserid)
                            select n.messageid).Distinct();
var ans = from m in Message
          where m.isactive == 1 && notificationMessages.Contains(m.messageid)
          select new { m.messageid, m.comment };