简体   繁体   English

SQL 到 LINQ 无法转换 SQL 连接查询与多个条件与“和”

[英]SQL to LINQ unable to convert SQL join query with multiple conditions with "and"

I was trying to convert a SQL Server query with multiple table joins and multiple conditions in a join to LINQ.我试图将具有多个表连接和多个条件的 SQL 服务器查询转换为 LINQ。 I am getting an error while trying to use multiple conditions in join using &&.尝试在使用 && 的连接中使用多个条件时出现错误。

Below is my SQL Server query.下面是我的 SQL 服务器查询。

SELECT j.ID,
       j.OnTime AS 'Alarm Appear Time',
       j.OffTime AS 'Alarm Disappear Time',
       j.OnNoticeTime AS 'Alarm Ack Time',
       j.OffNoticeTime AS 'Alarm Close Time',
       j.InstanceID AS 'Asset ID',
       i.RemarkPath AS 'Asset',
       j.PropertyID AS 'Message ID',
       p.Remark AS 'Alarm Message',
       a.X4AlarmGroup_ID AS 'Priority ID',
       g.Name AS 'Priority Group'
FROM [XAMRuntimeX4].[dbo].[X4Journals] j
    JOIN [XAMRuntimeX4].[dbo].[V_X4InstanceRemarks] i
        ON j.InstanceID = i.Instance_ID
    JOIN [XAMRuntimeX4].[dbo].[V_AutomationControlPropertyRemarks] p
        ON j.PropertyID = p.Property_ID
    JOIN [XAMControlX4].[dbo].[X4AlarmConfigs] a
        ON j.InstanceID = a.X4Instance_ID
           AND j.PropertyID = a.X4Property_ID
    JOIN [XAMControlX4].[dbo].[X4AlarmGroups] g
        ON a.X4AlarmGroup_ID = g.ID
WHERE i.Language = 'iv'
      AND p.LANGUAGE = 'iv'
ORDER BY j.OnTime DESC;

Below given is my attempt to convert it into LINQ下面给出的是我尝试将其转换为 LINQ

var finalAlarm = xAMRuntimeX4Context.X4Journals
    .Join(xAMControlX4Context.X4InstanceRemarks,
          j => j.InstanceID, i => i.Instance_ID, (j, i) => new { j, i })
    .Join(xAMControlX4Context.AutomationControlPropertyRemarks,
          ppc => ppc.j.PropertyID, p => p.Property_ID, (ppc, p) => new { ppc, p })
    .Join(xAMControlX4Context.X4AlarmConfigs,
          (ppc2 => ppc2.ppc.j.InstanceID, a => a.X4Instance_ID) &&
          (ppc2 => ppc2.ppc.j.PropertyID, a => a.X4Property_ID),
          (ppc2, a) => new { ppc2, a });

Remarks评论

  • Your LINQ attempt is missing the X4AlarmGroups .您的 LINQ 尝试缺少X4AlarmGroups
  • To join X4Journals and X4AlarmConfigs on two columns I used ValueTuples.为了在两列上加入X4JournalsX4AlarmConfigs ,我使用了 ValueTuples。
  • I also unwrapped the intermediate anonymous types.我还解开了中间匿名类型。
var finalAlarm = xAMRuntimeX4Context.X4Journals
    .Join(xAMControlX4Context.X4InstanceRemarks,
            j => j.InstanceID, i => i.Instance_ID, (j, i) => new { j, i })
    .Join(xAMControlX4Context.AutomationControlPropertyRemarks,
            ppc => ppc.j.PropertyID, p => p.Property_ID, (ppc, p) => new { ppc.j, ppc.i, p })
    .Join(xAMControlX4Context.X4AlarmConfigs,
            ppc2 => (ppc2.j.InstanceID, ppc2.j.PropertyID), a => (a.X4Instance_ID, a.X4Property_ID),
            (ppc2, a) => new { ppc2.j, ppc2.i, ppc2.p, a })
    .Join(xAMControlX4Context.X4AlarmGroups,
            ppc3 => ppc3.a.X4AlarmGroup_ID, g => g.ID, (ppc3, g) => new { ppc3.j, ppc3.i, ppc3.p, ppc3.a, g })
    .Where(ppc4 => ppc4.i.Language == "iv" && ppc4.p.Language == "iv")
.OrderBy(ppc4 => ppc4.j.OnTime)
.Select(x => new {
    x.j.ID,
    AlarmAppearTime = x.j.OnTime,
    AlarmDisappearTime = x.j.OffTime,
    AlarmAckTime = x.j.OnNoticeTime,
    AlarmCloseTime = x.j.OffNoticeTime,
    AssetID = x.j.InstanceID,
    Asset = x.i.RemarkPath,
    MessageID = x.j.PropertyID,
    AlarmMessage = x.p.Remark,
    PriorityID = x.a.X4AlarmGroup_ID,
    PriorityGroup = x.g.Name
});

See How to do joins in LINQ on multiple fields in single join .请参阅如何在 LINQ 中对单个连接中的多个字段进行连接

You cannot use the && operator to select multiple columns in a Linq method syntax join.您不能使用 && 运算符将 select 多个列中的 Linq 方法语法连接。 Instead you need to code your outer and inner key selectors to each return both key values together in a new anonymous object.相反,您需要对外部和内部键选择器进行编码,以在新的匿名 object 中同时返回两个键值。

In your case, something like:在您的情况下,类似于:

    .Join(xAMControlX4Context.X4AlarmConfigs,
          ppc2 => new { ppc2.ppc.j.InstanceID, ppc2.ppc.j.PropertyID },
          a => new { a.X4Instance_ID, a.X4Property_ID },
          (ppc2, a) => new { ppc2, a })

In Linq To SQL, thinking you have proper relations at database level, you seldom need joins.在 Linq 到 SQL 中,认为您在数据库级别有适当的关系,您很少需要连接。 Instead you use navigational properties.相反,您使用导航属性。 In your case, it is not clear if those relations are 1-to-1, 1-to-many, many-to-1 or many-to-many.在您的情况下,尚不清楚这些关系是一对一、一对多、多对一还是多对多。 It would matter just for getting the Remarkpath, Remark like properties.仅获取 Remarkpath、Remark 之类的属性就很重要。 Looking from your SQL, as it stands, we have to consider that they may lead to multiple rows, thus it translates to LinqToSQL as:从您的 SQL 来看,就目前而言,我们必须考虑到它们可能会导致多行,因此它将 LinqToSQL 转换为:

var finalAlarm = from j in xAMRuntimeX4Context.X4Journals
                 from i in j.X4InstanceRemarks.Where(x => x.Langauge == "iv")
                 from p in j.AutomationControlPropertyRemarks.Where(x => x.Langauge == "iv")
                 from a in j.X4AlarmConfigs
                 from g in a.X4AlarmGroups
                 select new
    {
        ID = j.ID,
        AlarmAppearTime = j.OnTime,
        AlarmDisappearTime = j.OffTime,
        AlarmAckTime = j.OnNoticeTime,
        AlarmCloseTime = j.OffNoticeTime,
        AssetID = j.InstanceID,
        Asset = i.RemarkPath,
        MessageId = j.PropertyId,
        AlarmMessage = p.Remark,
        PriorityID = a.X4AlarmGroup_ID,
        PriorityGroup = g.Name
    };

Note: You can use LinqPad to write this easier.注意:您可以使用 LinqPad 更轻松地编写此内容。 Connect to your database, and check the schema.连接到您的数据库,并检查架构。 It would show you the navigations, 1-to-many etc relations.它会向您显示导航、一对多等关系。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM