2015-10-05 164 views
2

我有一個可怕的時間試圖讓LINQ語句工作。LINQ:「枚舉沒有結果」

我一直在使用下面這篇文章既SQL語法和拉姆達嘗試:

C# Joins/Where with Linq and Lambda

這是我工作的SQL的樣子:

SELECT ws_lookup_OccupationGroup.Code 
FROM ws_lookup_OccupationGroup 
INNER JOIN ws_lookup_Occupation ON 
ws_lookup_OccupationGroup.Code = ws_lookup_Occupation.ws_lookup_OccupationGroup_Code 
WHERE (ws_lookup_Occupation.Code = N'413') 

這是我第一次嘗試,它產生沒有結果:

var query = from occupationGroup in db.ws_lookup_OccupationGroups 
      join occupations in db.ws_lookup_Occupations on occupationGroup.Code equals occupations.Code 
      where occupations.Code == model.Client.Client_Details_Enhanced.Occupation.Code 
      select new 
      { 
       OccupationGroup = occupationGroup, 
       Occupations = occupations 
      }; 

這是我的第二個嘗試使用Lamdba這也產生任何結果:

var queryLambda = db.ws_lookup_OccupationGroups 
        .Join(db.ws_lookup_Occupations, 
          occupation => occupation.Code, 
          occupationGroup => occupationGroup.Code, 
          (occupation, occupationGroup) => new 
          { 
           OCCUPATION = occupation, 
           OCCUPATIONGROUP = occupationGroup 
          }) 
        .Where(all => all.OCCUPATION.Code == model.Client.Client_Details_Enhanced.Occupation.Code); 

我看不出什麼錯誤......

我不知道是該有什麼意義,但我使用的代碼第一次實體框架 - 他是我的OccupationGroups &職業型號:

public class ws_lookup_OccupationGroup { 
    [Key] 
    [MaxLength(250)] 
    public string Code { get; set; } 
    [MaxLength(250)] 
    public string Name { get; set; } 
    public int SortOrder { get; set; } 
    public List<ws_lookup_Occupation> Occupations { get; set; } 
} 
public class ws_lookup_Occupation { 
    [Key] 
    [MaxLength(10)] 
    public string Code { get; set; } 
    [MaxLength(250)] 
    public string Name { get; set; } 
    [MaxLength(250)] 
    public string BarbadosMotorFactor { get; set; } 
    [MaxLength(250)] 
    public string TrinidadMotorFactor { get; set; } 
    [MaxLength(250)] 
    public string OtherRegionsMotorFactor { get; set; } 
} 
+0

您是否試過硬編碼值爲413而不是'model.Client.Client_Details_Enhanced.Occupation.Code'的語句? – CSL

+0

剛剛嘗試過 - 沒有得到任何結果:( –

+3

)你的查詢的兩個版本看起來都是正確的。你有沒有對數據庫進行剖析以查看實際發佈了哪些SQL? – Jamiec

回答

1

在SQL要加入以下

ws_lookup_OccupationGroup.Code = ws_lookup_Occupation.ws_lookup_OccupationGroup_Code 

但在LINQ的您加入上

occupationGroup.Code equals occupations.Code 

根據您的實體看上去完全像什麼我會假設你確實需要這個

occupationGroup.Code = occupations.ws_lookup_OccupationGroup_Code 

根據您的實體,它看起來像你可以做跟隨導航屬性而不是連接

var query = from occupationGroup in db.ws_lookup_OccupationGroups 
      where occupationGroup.Occupations.Any(
       o => o.Code == model.Client.Client_Details_Enhanced.Occupation.Code) 
      select occupationGroup; 

要獲得所有至少擁有一個職業的職業羣體h所需的代碼。或者,如果你只是想組和職業的組合,那麼你可以做

var query = from occupationGroup in db.ws_lookup_OccupationGroups 
      from occupation in occupationGroup.Occupations 
      where occupation.Code == model.Client.Client_Details_Enhanced.Occupation.Code 
      select new 
      { 
       occupationGroup, 
       occupation 
      }; 
+0

我無法弄清楚正確的連接語法應該是什麼 - 我對linq很陌生 - 你能幫助語法嗎? –

+0

@TrevorDaniel查看我的更新。您只需使用與相同列對應的屬性(它們通常具有相同的名稱)。 – juharr

+0

occupations.ws_lookup_OccupationGroup_Code不可見 - 只有一個List - 我用我的模型更新了我的問題......我仍然難倒了。 –

1

而不是直接回答你的問題,我寧願跟戰略的建議。其中一個策略是添加一個擴展方法,該方法將顯示您的實體框架查詢或IQueryable將運行的SQL。這可以通過創建單元測試並執行測試驅動開發方法或TDD來完成。

你知道你想獲得預期結果的SQL。最好是使用EF查詢,直到你得到一個SQL來傳遞你的結果。您可以調試集成測試,然後按照實現框架Linq to Entities代碼編寫的最終結果 - 您之後的SQL。

首先,我們可以創建以下的擴展方法:

public static class IQueryableExtensions 
    { 

     /// <summary> 
     /// Shows the sql the IQueryable query will be generated into and executed on the DbServer 
     /// </summary> 
     /// <param name="query">The IQueryable to analyze</param> 
     /// <param name="decodeParameters">Set to true if this method should try decoding the parameters</param> 
     /// <remarks>This is the generated SQL query in use for Entity Framework</remarks> 
     public static string ShowSql(this IQueryable query, bool decodeParameters = false) 
     { 
      var objectQuery = (ObjectQuery)query; 

      string result = ((ObjectQuery)query).ToTraceString(); 

      if (!decodeParameters) 
       return result; 

      foreach (var p in objectQuery.Parameters) 
      { 
       string valueString = p.Value != null ? p.Value.ToString() : string.Empty; 
       if (p.ParameterType == typeof(string) || p.ParameterType == typeof(DateTime)) 
        valueString = "'" + valueString + "'"; 
       result = result.Replace("@" +p.Name, p.Value != null ? valueString : string.Empty); 
      } 
      return result; 
     }  

} 

然後,我們需要從我自己的系統中的一些集成測試,樣品:

[TestFixture] 
    public class IqueryableExtensionsTest 
    { 

     [Test] 
     public void QueryableReturnsSqlAndDoesNotThrow() 
     { 
      using (var dbContext = ObjectContextManager.ScopedOpPlanDataContext) 
      { 
       var operations = from operation in dbContext.Operations 
        where operation.Status == (int) OperationStatusDataContract.Postponed 
        && operation.OperatingDate >= new DateTime(2015, 2, 12) 
        select operation; 
       string sql = operations.ShowSql(); 
       Assert.IsNotNull(sql); 
      } 
     } 

    } 

雖然你當然可以用Linqpad來找到你之後的EF查詢和SQL,這種策略的好處是你可以在Visual Studio中將它用於更復雜的真實世界場景,與在VS和Linqpad之間切換相比,你也可以獲得更好的調試體驗。

如果您調試了這樣的集成測試,那麼您可以觀察正在生成的SQL。請注意,如果要運行Integration Test並不對其進行調試,則還可以執行Console.WriteLineDebug.WriteLine來觀察輸出。