2015-10-05 104 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来观察输出。