Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么这一疑问会引起“怀疑”;SQL语句嵌套太深;?_C#_Sql_Linq_Linq To Entities - Fatal编程技术网

C# 为什么这一疑问会引起“怀疑”;SQL语句嵌套太深;?

C# 为什么这一疑问会引起“怀疑”;SQL语句嵌套太深;?,c#,sql,linq,linq-to-entities,C#,Sql,Linq,Linq To Entities,昨天,一位好心人帮我为Linq-to-Entities构建了一个PredicateBuilder 看起来很好,但是完整的查询生成了这个长达70000行的可怕的东西(太长了,无法粘贴),并且SQL语句嵌套得太深了 以下是上下文: 用户正在寻找符合其标准的动物列表,特别是关于能力的动物。 在GUI中,对于每种能力类型(例如:“狂躁”、“敏捷”等),用户可以选择一个修饰符(“>”、“敏捷中的3”或“所有具有狂躁能力” { filter=e=>e.AllAbilities.Any(a=>a.TypeId

昨天,一位好心人帮我为
Linq-to-Entities
构建了一个
PredicateBuilder
看起来很好,但是完整的查询生成了这个长达70000行的可怕的东西(太长了,无法粘贴),并且SQL语句嵌套得太深了

以下是上下文:
用户正在寻找符合其标准的动物列表,特别是关于能力的动物。
在GUI中,对于每种能力类型(例如:“狂躁”、“敏捷”等),用户可以选择一个修饰符(“>”、“敏捷中的3”或“所有具有狂躁能力<10且敏捷能力潜力=2的动物”

关于数据库:

Player
带有列
Id

Animal
带列
Id

能力
带列:

  • Id
  • AnimalId
  • TypeId
    (表示枚举,可以是“潜在”、“出生潜能”或“技能”)
  • AbilityId
    (表示可以是“敏捷性”或“疯狂性”的枚举)
因此,每只动物都有一个
AllAbilities
属性,这是一个
i集合


非常感谢!

在执行动态筛选时,请尝试在表达式之外执行更多的静态计算。这样您将获得更好的查询,因为当前EF除了在(…)中构建静态
列表条件外,不优化常量表达式

但是当前代码的主要问题是在能力筛选器中使用了
FirstOrDefault
。一般来说,尽量避免使用任何可能导致SQL子查询的查询构造类型,因为正如您所看到的,出于某种原因,EF嵌套了所有子查询,因此您得到了畸形的SQL和错误。安全的构造是要使用转换为SQL的任何
存在子查询,则不需要嵌套

试试这个,看看你会得到什么:

static Expression<Func<Animal, bool>> AbilitySkillFilter(Criteria.ModifierE modifier, int abilityId, int userValue)
{
    Expression<Func<GameAnimal, bool>> filter = null;
    bool includeMissing = false;
    if (modifier == Criteria.ModifierE.More) // User chose ">"
    {
        filter = e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId && a.Value >= userValue);
        includeMissing = userValue <= 0;
    }
    else if (modifier == Criteria.ModifierE.Equal) // User chose "="
    {
        filter = e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId && a.Value == userValue);
        includeMissing = userValue == 0;
    }
    else if (modifier == Criteria.ModifierE.Less) // User chose "<"
    {
        filter = e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId && a.Value >= userValue);
        includeMissing = userValue >= 0;
    }
    if (filter != null && includeMissing)
        filter = filter.Or(e => !e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId));
    return filter;
}

static Expression<Func<Animal, bool>> AbilityPotentialFilter(Criteria.ModifierE modifier, int abilityId, int userValue)
{
    if (modifier == Criteria.ModifierE.More)
        return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId)
            ? e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId && a.Value >= userValue)
            : e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.BirthPotential && a.AbilityId == abilityId && a.Value >= userValue);
    else if (modifier == Criteria.ModifierE.Equal)
        return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId)
            ? e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId && a.Value == userValue)
            : e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.BirthPotential && a.AbilityId == abilityId && a.Value == userValue);
    else if (modifier == Criteria.ModifierE.Less)
        return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId)
            ? e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId && a.Value <= userValue)
            : e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.BirthPotential && a.AbilityId == abilityId && a.Value <= userValue);
    else
        return null;
}
静态表达式能力killfilter(Criteria.modifier修饰符、int-abilityId、int-userValue)
{
表达式过滤器=null;
bool includeMissing=false;
if(modifier==Criteria.modifire.More)//用户选择“>”
{
filter=e=>e.AllAbilities.Any(a=>a.TypeId==(int)Ability.TypeE.Skill&&a.AbilityId==AbilityId&&a.Value>=userValue);
includeMissing=userValue e.AllAbilities.Any(a=>a.TypeId==(int)Ability.TypeE.Skill&&a.AbilityId==AbilityId&&a.Value==userValue);
includeMissing=userValue==0;
}

else if(modifier==Criteria.modifire.Less)//用户选择“SQL Server是否与应用程序在同一台计算机上工作?如果是,可能会获取所有筛选数据(循环中没有筛选)对本地集合进行循环筛选,这是一个选项。与其将if条件放入谓词中,为什么不有条件地应用它们,如
if(speciesId!=-1)filter=filter.and(e=>e.speciesId==speciesId);
。这可能有助于降低查询的复杂性。@schlonzo:是的。因此建议您执行
等待GetAll(过滤器)
两次,一次在循环前,一次在循环结束时?@juharr:的确,你说得对,我会这样编辑我的代码。但是如果用户输入每个条件,他仍然无法得到结果:(@Flash_Back即使所有的
如果
都是真的,它仍然会导致不太复杂的查询。虽然我认为循环中的东西更有可能是罪魁祸首。@juharr是的,我想你会得到所有过滤过的数据,直到程序的循环过滤部分。将其存储在列表中或使用
ToListSync()的东西中)
,然后对列表中的其他内容进行筛选。你可能无法想象我(再次)有多么感激你!它不仅工作得非常好,而且我也了解实际情况,并且能够在我的项目中随处使用此基础。我用新的SQL输出编辑了我的第一篇文章,从70000行到60行,令人难以置信!再次感谢花时间帮助我,希望我能做的不仅仅是接受答案;)不客气,很高兴你帮了忙:)祝你的项目好运,干杯!
static Expression<Func<Animal, bool>> AbilitySkillFilter(Criteria.ModifierE modifier, int abilityId, int userValue)
    {
        if (modifier == Criteria.ModifierE.More) // User chose ">"
            return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId)
                ? e.AllAbilities.FirstOrDefault(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId).Value >= userValue
                : value <= 0;
        else if (modifier == Criteria.ModifierE.Equal) // User chose "<"
            return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId)
                ? e.AllAbilities.FirstOrDefault(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId).Value == userValue
                : value == 0;
        else if (modifier == Criteria.ModifierE.Less) // User chose "<"
            return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId)
                ? e.AllAbilities.FirstOrDefault(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId).Value <= userValue
                : value >= 0;
        else
            return null;
    }

    static Expression<Func<Animal, bool>> AbilityPotentialFilter(Criteria.ModifierE modifier, int abilityId, int userValue)
    {
        if (modifier == Criteria.ModifierE.More)
            return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId)
                ? e.AllAbilities.FirstOrDefault(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId).Value >= userValue
                : e.AllAbilities.FirstOrDefault(a => a.TypeId == (int)Ability.TypeE.BirthPotential && a.AbilityId == abilityId).Value >= userValue;
        else if (modifier == Criteria.ModifierE.Equal)
            return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId)
                ? e.AllAbilities.FirstOrDefault(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId).Value == userValue
                : e.AllAbilities.FirstOrDefault(a => a.TypeId == (int)Ability.TypeE.BirthPotential && a.AbilityId == abilityId).Value == userValue;
        else if (modifier == Criteria.ModifierE.Less)
            return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId)
                ? e.AllAbilities.FirstOrDefault(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId).Value <= userValue
                : e.AllAbilities.FirstOrDefault(a => a.TypeId == (int)Ability.TypeE.BirthPotential && a.AbilityId == abilityId).Value <= userValue;
        else
            return null;
    }
static Expression<Func<Animal, bool>> AbilitySkillFilter(Criteria.ModifierE modifier, int abilityId, int userValue)
{
    Expression<Func<GameAnimal, bool>> filter = null;
    bool includeMissing = false;
    if (modifier == Criteria.ModifierE.More) // User chose ">"
    {
        filter = e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId && a.Value >= userValue);
        includeMissing = userValue <= 0;
    }
    else if (modifier == Criteria.ModifierE.Equal) // User chose "="
    {
        filter = e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId && a.Value == userValue);
        includeMissing = userValue == 0;
    }
    else if (modifier == Criteria.ModifierE.Less) // User chose "<"
    {
        filter = e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId && a.Value >= userValue);
        includeMissing = userValue >= 0;
    }
    if (filter != null && includeMissing)
        filter = filter.Or(e => !e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Skill && a.AbilityId == abilityId));
    return filter;
}

static Expression<Func<Animal, bool>> AbilityPotentialFilter(Criteria.ModifierE modifier, int abilityId, int userValue)
{
    if (modifier == Criteria.ModifierE.More)
        return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId)
            ? e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId && a.Value >= userValue)
            : e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.BirthPotential && a.AbilityId == abilityId && a.Value >= userValue);
    else if (modifier == Criteria.ModifierE.Equal)
        return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId)
            ? e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId && a.Value == userValue)
            : e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.BirthPotential && a.AbilityId == abilityId && a.Value == userValue);
    else if (modifier == Criteria.ModifierE.Less)
        return e => e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId)
            ? e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.Potential && a.AbilityId == abilityId && a.Value <= userValue)
            : e.AllAbilities.Any(a => a.TypeId == (int)Ability.TypeE.BirthPotential && a.AbilityId == abilityId && a.Value <= userValue);
    else
        return null;
}