LINQ:"枚举没有产生任何结果"

时间:2015-10-05 10:32:01

标签: c# linq

我正在努力让LINQ语句正常工作。

我在这篇文章后尝试过使用SQL语法和lambda:

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);

我只是看不出有什么问题......

我不知道这是否有任何相关性,但我使用的是Code First Entity Framework - 他是我职业组的模型&职业:

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; }
}

2 个答案:

答案 0 :(得分:3)

我宁愿提出策略建议,而不是直接回答你的问题。然后,一种策略是添加一个扩展方法,该方法将显示您的实体框架查询或IQueryable将运行的SQL。这可以通过创建单元测试并执行测试驱动开发方法或TDD的方式完成。

您知道要获得预期结果的SQL。最好使用EF查询,直到获得一个能够提供您所获得结果的SQL。您可以调试集成测试,然后按照最终结果 - 您正在使用的SQL - 在Entity Framework Linq to Entities代码中编写。

首先,我们可以创建以下扩展方法:

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.WriteLine Debug.WriteLine 来观察输出。

答案 1 :(得分:2)

在您的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;

获取至少一个拥有所需代码的职业的所有职业组。或者,如果你只想要小组和职业的组合,那么你可以做到

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
            };