2012-02-27 74 views
0

首先,我不得不承認,我是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) 

這工作得很好,但很明顯是缺少「不存在......」部分(最後3行本帖頂部的SQL代碼)。 我知道Linq沒有「不存在」,但是你可以使用「Any」方法。 下面是這個其他地方在我的代碼的工作示例:

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)。 任何幫助將不勝感激。

回答

0

我會做這樣的事情:

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 
+0

Arion,謝謝你的回答。我沒有嘗試過,但我可以看到這會起作用。但天哪,這是很多代碼。這就是爲什麼我試圖讓它使用lambda表達式工作。看看我幾分鐘前發佈的答案。這顯然不是真正的答案,而是一種解決方法,它使我獲得正確的結果。 – Peter 2012-02-28 09:23:32

+0

更新了答案 – Arion 2012-02-28 10:35:43

0

這不是問題的答案,但它是一個工作圍繞確實讓我結果,我需要:

 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表達式的工作解決方案(因爲這有點像作弊),我很樂意聽到它。