【问题标题】:How to reference the same table twice?如何引用同一张表两次?
【发布时间】:2012-02-28 18:35:33
【问题描述】:

首先,我必须承认我是 Linq 和 Lambda 表达式的新手。 我正在尝试将以下 SQL 语句转换为 Linq 语句(使用 lamda 表达式):

select *
from dbo.tblStockTransfers t1,
dbo.tblSuppliers t2
where t1.SupplierID = t2.SupplierID
and t2.WarehouseID in (1,2,3)
and t1.GoodsPickedUp = 1
and Not exists
(select 1 from dbo.tblStockTransfers t3
where t3.TransferOutID = t1.TransferID and t3.TransferConfirm = 1)

我的 StockTransfer 类是一个聚合根,并且有它自己的存储库。 现在到目前为止,我得到了以下信息(变量 allowedWarehouses 包含仓库 ID 列表):

Return GetObjectSet().Where(Function(st) allowedWarehouses.Contains(st.Supplier.WarehouseID) And st.GoodsPickedUp = True)

这工作正常,但显然缺少“并且不存在......”部分(这篇文章顶部的 SQL 代码的最后 3 行)。 我知道 Linq 没有“不存在”,但您可以为此使用“任何”方法。 这是我代码中其他地方的一个工作示例:

Return GetObjectSet().Where(Function(sw) sw.Active = True And Not sw.Suppliers.Any(Function(sp) sp.WarehouseID = sw.Id))

这很好用,并且会给我任何尚未链接到供应商的仓库。 正如您在上面的示例中看到的那样,这很好,因为我指的是相关表“供应商”。

但是,在我现在尝试转换为 Linq 的 SQL 代码中,“不存在”不在链接表上,而是在其自身上。有没有办法可以在主表上创建第二个引用并在“.. not ..any”部分使用它。可能是这样的:

Return GetObjectSet().Where(Function(st) allowedWarehouses.Contains(st.Supplier.WarehouseID) And st.GoodsPickedUp = True And Not st2.Any(st2.TransferOutID = st.TransferId and st2.TransferConfirm = true)

但我不知道如何定义 st2(即在这种情况下 st2 将是 StockTransfer 的第二个别名)。 任何帮助将不胜感激。

【问题讨论】:

    标签: linq linq-to-sql lambda


    【解决方案1】:

    这不是问题的答案,但它是一种解决方法,它确实让我得到了我需要的结果:

            Dim st1 As List(Of StockTransfer) = GetObjectSet.Where(Function(st) allowedWarehouses.Contains(st.Supplier.WarehouseID) And st.GoodsPickedUp = True).ToList
            Dim st2 As List(Of StockTransfer) = GetObjectSet.Where(Function(st) st.TransferConfirm = True).ToList
            For Each st As StockTransfer In st2
                st1.RemoveAll(Function(x) x.Id = st.TransferOutID)
            Next
            Return st1
    

    我显然是在作弊,将查询分成两部分,每个部分都在一个列表中,然后我从列表 1 中删除我在列表 2 中的所有项目(删除那些通常是被“不存在”部分忽略)。

    但是,如果有人可以使用 Linq 和 lambda 表达式提出可行的解决方案,我很乐意听到(因为这确实有点像作弊)。

    【讨论】:

      【解决方案2】:

      我会这样做:

      Dim lsWareHouseIds As New List(Of Integer)() From {1,2,3}
      dim obj= ( _ 
                      From t1 in db.tblStockTransfers  _ 
                      join t2 in db.tblSuppliers _ 
                          on t1.SupplierID equals company.SupplierID _
                      where lsWareHouseIds.Contains(t2.WarehouseID) _ 
                      andalso t1.GoodsPickedUp =1 _ 
                      andalso Not _
                          (
                              from t3 in db.tblStockTransfers _ 
                              where t3.TransferConfirm=1 _ 
                              select t3.TransferOutID _ 
                          ).Contains(t1.TransferID) _ 
                      select t1 _ 
                   )
      

      我确实看到您发表评论并回答了。你不能这样做吗:

      GetObjectSet.Where(Function(st) _ 
      allowedWarehouses.Contains(st.Supplier.WarehouseID) And st.GoodsPickedUp = True _ 
      Andalso Not _ 
      GetObjectSet.Where(Function(st) _ 
      st.TransferConfirm = True).Any(Function(x) x.Id =  st.TransferOutID)).ToList
      

      【讨论】:

      • Arion,感谢您的回答。我还没有尝试过,但我可以看到它会起作用。但是天哪,那是很多代码。这就是为什么我尝试使用 lambda 表达式让它工作。看看我几分钟前发布的答案。这显然不是真正的答案,而是一种让我得到正确结果的解决方法。
      猜你喜欢
      • 2018-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-05
      • 1970-01-01
      • 1970-01-01
      • 2021-06-16
      • 1970-01-01
      相关资源
      最近更新 更多