如何两次引用同一个表?

时间:2012-02-27 12:48:17

标签: linq linq-to-sql lambda

首先,我必须承认我在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没有“不存在”,但你可以使用“Any”方法。 以下是我的代码中其他地方的一个工作示例:

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

这很好,并且会给我任何与供应商无关的仓库。 正如您在上面的示例中所看到的,这很好,因为我指的是相关表“供应商”。

但是,在我现在尝试转换为Linq的SQL代码中,“not exists”不在链接表上,而是在其自身上。有没有办法在主表上创建第二个引用,并在“.. 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的第二个别名)。 非常感谢任何帮助。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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表达式提出一个有效的解决方案(我觉得这有点像作弊),我很乐意听到它。