【问题标题】:Unable to convert SQL Query to LINQ Query for Left Outer Join无法将 SQL 查询转换为左外连接的 LINQ 查询
【发布时间】:2015-02-06 14:27:27
【问题描述】:

问题陈述:

我正在尝试将我的一个 Sql 转换为 linq 查询,但我无法获得所需的输出。谁能建议我该怎么做?

SQL 查询:

SELECT AssetTagging.AssetID, AssetTagging.AssetDescription, [Return].RequestStatus
FROM  AssetTagging
LEFT OUTER JOIN [Return] ON AssetTagging.AssetID = [Return].AssetID
LEFT OUTER JOIN Issue ON AssetTagging.AssetID = Issue.AssetID
WHERE (Issue.AssetID IS NULL) OR ([Return].RequestStatus = 'Approved')

我正在使用的 Linq 查询:

var result = (from at in db.AssetTagging.AsEnumerable()
                  join r in db.Return on at.AssetID equals r.AssetID
                  orderby at.AssetID
                  where !db.Issue.Any(issue=>issue.AssetID==at.AssetID) || r.RequestStatus=="Approved"
                  select new globalTestModel
                  {
                    model1=at
                  }).ToList();


//I know that in Linq query I'm using Inner join instead of Left Join,but i'm getting error if i use left join instead of inner join?

我做错了什么??

有什么建议可以在 Linq 中获得所需的查询,例如 Sql?

资产标签表:

问题表:

返回表:

期望的输出:

【问题讨论】:

  • LINQ to SQL Left Outer Join 的可能重复项
  • @vittore:但是你分享的链接我之前提到的将我的内连接转换为左外连接但它给出了错误,比如对象引用未设置为对象的实例。我已经改变了它作为join r in db.Return on at.AssetID equals r.AssetID into t from rt in t.DefaultIfEmpty() 和在哪里条件rt.RequestStatus=="Approved"。我认为哪里条件给出错误
  • 我看不到您引用评论的链接的位置。链接主题中的示例告诉您使用join r in db.Return on at.AssetID equals r.AssetID into joinedReturns
  • 您能否更具体地说明问题所在?您收到什么错误或数据与您预期的不符?问题可能只是您的orderby 在您的where 之前,因此更多上下文将非常有用。

标签: sql asp.net-mvc linq


【解决方案1】:

您需要删除.AsEnumerable(),因为您希望将查询转换为sql。现在它将使用linq-to-objects,如果您使用linq-to-object 的左连接,则需要检查空引用异常。 rt 可以为 null,所以 rt.RequestStatus 会抛出异常。

*我相信rt 在你的例子中应该是r

您无法投影到现有实体,因此您需要将您的选择更改为:

select new PocoClass
{
  model1=at 
}

//New class definition
public PocoClass
{
  public AssetTagging model1 { get; set; }
}

【讨论】:

  • 是的,不是 rt,我已经更新了我的问题,请您再检查一次。我需要它作为 .AsEnumerable,因为我将 Enumerable 模型绑定到我的视图。
  • 嗨,我检查了。AsEnumerable 不是问题。你能帮我在资产标记和返回表之间使用左连接而不是内连接。而不是左连接的内连接,我使用了@987654330 @ ,但它给出了错误
  • 它给出了错误,因为对象引用未设置为仅用于左外连接而不是内连接的对象实例。出了什么问题??
  • @VishalIPatil - AsEnumerable() 是问题所在。如果删除它会发生什么?
  • 如果我删除 AsEnumerable(),我会收到异常,因为 Unable to create a constant value of type 'globalTestModel'. Only primitive types or enumeration types are supported in this context.globalTestModel 是模型的集合。
【解决方案2】:

你需要这样做:

 var result = from at in db.AssetTagging
              join r in db.Returns on at.AssetID equals r.AssetID into a
              from returns into a.DefaultIfEmpty()
              join i in db.Issues on at.AssetID equals I.AssetID into b
              from issues into b.DefaultIfEmpty()
              where issues.AssetID != null || returns.RequestStatus == "Approved"
              select new
                    {
                      AssetID = at.AssetID,
                      AssetDescription = at.AssetDescription,
                      Status = returns != null ? returns.RequestStatus : null
                    }.ToList();

【讨论】:

  • 这将给对象引用错误作为问题并且返回为空
  • @Vishal I Patil 我正在检查 null 所以它不应该抛出异常
【解决方案3】:

尝试如下:

from at in db.AssetTagging
join r in db.Return on at.AssetID equals r.AssetID into res1
from atr in res1.DefaultIfEmpty()
join  i in db.Issues on i.AssetID==at.AssetID into res2
from obj in res2.DefaultIfEmpty()
select at
where i.AssetID == null || r.RequestStatus equals "Approved"

只需进行两次左外连接,然后在 where 条件下进行过滤。

也可以先看看thismsdn 关于left outer join using linq 的文章。

【讨论】:

    【解决方案4】:

    尝试以下我假设您仍然想要 r 为空的情况,除非 r 不为空并且请求状态 = 已批准。

    在检查请求状态之前,您必须检查以验证 r!=null,并且您仍然需要在 r 为 null 时包含以获取完整的结果集。我没有对此进行测试,但这应该会让你朝着正确的方向前进。

    祝你好运。

      var result = (from at in db.AssetTagging
                   join r in db.Return.DefaultIfEmpty()
                   on at.AssetID equals r.AssetID
                   join i in db.Issue.DefaultIfEmpty()
                   on  at.AssetID equals i.AssetID
                   where 
                   (r == null || (r!=null && r.RequestStatus == "Approved"))
                   || i == null
                   select new {
                    at.AssetID,
                    at.AssetDescription,
                    IssueID = (i!=null) ? i.IssueID : null),
                    ReturnID = (r!=null) ? r.ReturnID: null),
                    ReturnStatus = (r!=null) 
                         ? r.ReturnStatus 
                         : null}).ToList();
    

    【讨论】:

    • 嗨,它从 AssetTagging 表中生成所有行,我需要根据 i.AssetID IS NULLr.RequestStatus="Approved' 对其进行过滤,如何在 LINQ 中实现这一点。
    • 根据您的新要求修改
    【解决方案5】:

    我知道这并不完全符合您的要求,但无论如何它可能会有用。

    如果您有权访问数据库来执行 SQL 查询,我建议您创建一个视图。然后,您可以像处理表一样将视图拖放到 DBML 文件中,并在 C# 代码中使用更简单的 Linq 表达式。

    CREATE VIEW [Asset_Issue_Return_Joined] AS
    SELECT AssetTagging.AssetID, AssetTagging.AssetDescription, [Return].RequestStatus
    FROM  AssetTagging
    LEFT OUTER JOIN [Return] ON AssetTagging.AssetID = [Return].AssetID
    LEFT OUTER JOIN Issue ON AssetTagging.AssetID = Issue.AssetID
    WHERE (Issue.AssetID IS NULL) OR ([Return].RequestStatus = 'Approved')
    

    【讨论】:

      【解决方案6】:

      这是完整的查询

        var result = (from assetTagging in db.AssetTagging
                      join return0 in db.Return on assetTagging.AssetID equals return0.AssetID into returns
                      from return0 in returns.DefaultIfEmpty()
                      join issue in db.Issue on assetTagging.AssetID equals issue.AssetID into issues
                      from issue in issues.DefaultIfEmpty()
                      where issue.AssetID == null || return0.RequestStatus == "Approved"
                      select new
                      {
                         assetTagging.AssetID,
                         assetTagging.AssetDescription,
                         return0.RequestStatus
                      }).ToList();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-02
        • 1970-01-01
        • 1970-01-01
        • 2019-12-17
        相关资源
        最近更新 更多