2013-10-01 23 views
1

是否有可能檢查LINQ查詢中的空值,當值爲空,它執行額外的(子)查詢,一次全部?檢查值是否爲空,當它是,執行額外(子)查詢

說明

我有我的數據庫中聲明默認的按鈕,默認描述。用戶可以自定義這些按鈕,這些設置存儲在ButtonLocations表中。現在,每個按鈕都有一個標準描述,用戶可以編輯這個描述。當用戶編輯說明時,它將存儲在我的數據庫的Descriptions表中。 當我檢索所有按鈕時,首先檢查按鈕是否有特定的描述(在按鈕位置,左連接)。如果這不是真(如此),我檢索默認的描述。

目前我得到所有我的實體與他們的描述,然後我循環遍歷所有他們檢查值是否爲空。這會導致對數據庫的多個查詢。

var temp = (from bl in context.buttonLocations 
        join b in context.Buttons 
        on bl.ButtonID equals b.ButtonID into buttons 
        from button in buttons.DefaultIfEmpty() 
        join d in context.Descriptions 
        on new 
        { 
         ID = bl.ButtonLocationID, 
         langID = languageID, 
         originID = descriptionOriginID 
        } 
        equals new 
        { 
         ID = d.ValueID, 
         langID = d.LanguageID, 
         originID = d.DescriptionOriginID 
        } 
        into other 
        where bl.ButtonGroupID == buttonGroupId 
        from x in other.DefaultIfEmpty() 
        select new 
        { 
         Button = button, 
         ButtonLocation = bl, 
         Description = x 
        }).ToList(); 

     // Retrieve default descriptions if no specific one is set 
     foreach (var item in temp) 
     { 
      if (item.Description == null) 
      { 
       item.Description = context.Descriptions 
        .FirstOrDefault(x => x.ValueID == item.Button.ButtonID && x.LanguageID == languageID && x.DescriptionOriginID == (short)DescriptionOriginEnum.Button); 
      } 
     } 

回答

0

我認爲使用聚結操作科林的答案應該工作,但如果它不能爲您做出可以嘗試做一個子查詢它得到這兩個選項,然後按優先定製源訂購併取得最高紀錄。 (我假設在這裏,任何特定的按鈕,只有真正有一個描述,而多描述不應導致多個按鈕。)

var temp = (from bl in context.buttonLocations 
     join b in context.Buttons 
     on bl.ButtonID equals b.ButtonID into buttons 
     from button in buttons.DefaultIfEmpty() 
     let description = (
       from d in context.Descriptions 
       where 
        d.LanguageID == languageID 
       && (
         (
         d.ValueID == bl.ButtonLocationID 
         && d.DescriptionOriginID == descriptionOriginID 
        ) 
        || 
         (
         d.ValueID == b.ButtonID 
         d.DescriptionOriginID == (short)DescriptionOriginEnum.Button 
        ) 
        ) 
       // this line puts custom descriptions first 
       orderby d.DescriptionOriginID == (short)DescriptionOriginEnum.Button 
         ? 1 
         : 0 
       select d 
       ) 
       // this will get a custom description if there was one, otherwise 
       // the first one will be the default description 
       .FirstOrDefault() 
     where bl.ButtonGroupID == buttonGroupId 
     select new 
     { 
      Button = button, 
      ButtonLocation = bl, 
      Description = description 
     }) 
     .ToList(); 

這顯然是一個有點尷尬,而且很可能不是最有效的查詢。我會嘗試先將聚結操作符移動到let description = d ?? /*subselect*/行。

0

null coalescing operator應該在這裏工作。事情是這樣的:

..... 
select new 
{ 
    Button = button, 
    ButtonLocation = bl, 
    Description ?? context.Descriptions 
         .FirstOrDefault(
         x => x.ValueID == button.ButtonID 
         && x.LanguageID == languageID 
         && x.DescriptionOriginID == (short)DescriptionOriginEnum.Button) 
}) 
+0

我已經試過了,它沒有工作。它給出了以下錯誤:*'無法創建'描述'類型的空常量值。 '* – Loetn

+0

我認爲你的錯誤來自實體框架,因爲它不能將你的代碼翻譯成sql。 '(short)DescriptionOriginEnum.Button'可能是罪魁禍首 - 在構造查詢之前嘗試將它分配給一個'short'變量。這可能有所幫助:http://stackoverflow.com/a/17847159/150342 – Colin

+0

這兩個建議的解決方案都沒有幫助。我猜這是不可能的? – Loetn