2012-09-24 108 views
1

在我的工作,我們的主要應用是很久以前寫的前n層是一個真正的東西,ERGO - 它擁有噸,噸業務邏輯的存儲特效和這樣的開始處理。轉換SQL到LINQ愁楚

因此,我們終於決定咬緊牙關,使其不吸那麼糟糕。我一直負責將一個900多行的sql腳本轉換爲一個.NET EXE,我在C#/ Linq中做了這些。問題是......在另一項工作中,過去5 - 6年裏,我一直在做Linq,所以我的SQL已經變得有些生疏,而我正在轉換的一些東西我從來沒有在Linq中嘗試過,所以我打了一些路障。

反正夠牢騷。我在與下面的SQL語句的麻煩

,我認爲由於他是在一個臨時表和派生表的加盟。這裏的SQL:

insert into #processedBatchesPurgeList 
    select d.pricebatchdetailid 
    from pricebatchheader h (nolock) 
    join pricebatchstatus pbs (nolock) on h.pricebatchstatusid = pbs.pricebatchstatusid 
    join pricebatchdetail d (nolock) on h.pricebatchheaderid = d.pricebatchheaderid 
    join 
    ( -- Grab most recent REG. 
     select 
      item_key 
      ,store_no 
      ,pricebatchdetailid = max(pricebatchdetailid) 
     from pricebatchdetail _pbd (nolock) 
     join pricechgtype pct (nolock) on _pbd.pricechgtypeid = pct.pricechgtypeid 
     where 
      lower(rtrim(ltrim(pct.pricechgtypedesc))) = 'reg' 
      and expired = 0 
     group by item_key, store_no 
    ) dreg 
     on d.item_key = dreg.item_key 
     and d.store_no = dreg.store_no 
    where 
     d.pricebatchdetailid < dreg.pricebatchdetailid -- Make sure PBD is not most recent REG. 
     and h.processeddate < @processedBatchesPurgeDateLimit 
     and lower(rtrim(ltrim(pbs.pricebatchstatusdesc))) = 'processed' -- Pushed/processed batches only. 

所以這是第一個提出整體的問題:如何處理Linq中的臨時表?這個腳本使用了大約10個。我目前有他們作爲列表。問題是,如果我嘗試在查詢中加入一個.Join(),我會得到「本地序列不能用於查詢運算符的LINQ to SQL實現,但Contains運算符除外」。錯誤。

我能得到加入到派生表使用2個查詢工作,就這樣一個人會不會得到如同噩夢般長:

var dreg = (from _pbd in db.PriceBatchDetails.Where(pbd => pbd.Expired == false && pbd.PriceChgType.PriceChgTypeDesc.ToLower().Trim() == "reg") 
        group _pbd by new { _pbd.Item_Key, _pbd.Store_No } into _pbds 
        select new 
        { 
         Item_Key = _pbds.Key.Item_Key, 
         Store_No = _pbds.Key.Store_No, 
         PriceBatchDetailID = _pbds.Max(pbdet => pbdet.PriceBatchDetailID) 
        }); 

     var query = (from h in db.PriceBatchHeaders.Where(pbh => pbh.ProcessedDate < processedBatchesPurgeDateLimit) 
        join pbs in db.PriceBatchStatus on h.PriceBatchStatusID equals pbs.PriceBatchStatusID 
        join d in db.PriceBatchDetails on h.PriceBatchHeaderID equals d.PriceBatchHeaderID 
        join dr in dreg on new { d.Item_Key, d.Store_No } equals new { dr.Item_Key, dr.Store_No } 
        where d.PriceBatchDetailID < dr.PriceBatchDetailID 
        && pbs.PriceBatchStatusDesc.ToLower().Trim() == "processed" 
        select d.PriceBatchDetailID); 

因此該查詢給出了預期的效果,這是我我拿着一個List,但後來我需要將該查詢的結果加入到從數據庫中選擇的另一個結果中,這導致我回到前面提到的「本地序列無法使用...」錯誤。

查詢是這樣的:

insert into #pbhArchiveFullListSaved 
    select h.pricebatchheaderid 
    from pricebatchheader h (nolock) 
     join pricebatchdetail d (nolock) 
      on h.pricebatchheaderid = d.pricebatchheaderid 
     join #processedBatchesPurgeList dlist 
      on d.pricebatchdetailid = dlist.pricebatchdetailid -- PBH list is restricted to PBD purge list rows that have PBH references. 
    group by h.pricebatchheaderid 

上#processedBatchesPurgeList的加入有我遇到了這個問題。

所以呃...幫助嗎?我從來沒有寫過這樣的SQL,當然也沒有試圖將它轉換爲Linq。

+5

如果你的sql使用很多臨時表,並且你不能重構它們,存儲過程可能是最好的選擇。 – jrummell

+1

第二。如果這是工作,它看起來像非常乾淨的TSQL。 #processedBatchesPurgeList可能很昂貴,並且會實現物化,因此在稍後的連接中不會重新評估多次。那些(nolock)不是偶然的。在你太過分之前,比較LINQ與TSQL的性能。 – Paparazzi

+0

我也會同意你很可能在浪費你的時間轉換一些有用的東西,然而很酷的LINQ!重寫這個腳本的原因是什麼?爲什麼不直接從exe中啓動sql腳本?你知道這是有道理的。 – Tom

回答

0

正如以上,這不再被改寫爲LINQ的評論中指出。

希望獲得性能提升,同時實現更好的SOX合規性,這是首先重寫的全部原因。

我很滿意只需滿足SOX合規性問題。

謝謝大家。