如何将复杂查询分解为不同的方法以实现更少的代码复杂性

时间:2015-03-14 12:01:39

标签: linq code-complexity

我有一个复杂的查询需要分解成不同的方法才能满足NFR代码复杂性标准。

我知道这只是为了满足所需的标准,但是这个查询可以分解成更小的块吗?

var query = (from a1 in a 
             join b1 in b
                 on a1.id1 equals b1.id1
             join c1 in c
                 on b1.id equals c1.id
             join d1 in d
                 on c1.id1 equals d1.id
             where (d1.Contains("text"))
             select d1);

2 个答案:

答案 0 :(得分:4)

根据您使用的是Linq-to-SQL还是Linq-to-Entities,可以通过代码表示关系,您可以简单地使用导航属性:

from d1 in d 
where d1.C.B.A != null
     && d1.Contains("text")
select d1;

实体框架将知道忽略代码中可能的空引用异常,因为它会将其表示为查询,并且实际上不会运行代码。

如果这是不可能的,我假设您使用的是Visual Studio 2012代码复杂性功能,它不会查看代码复杂性,而是使用 IL 复杂性。 Linq查询倾向于在引擎盖下产生大量复杂性,这在代码中是不可见的。

我会忽略复杂性警告,因为将这个非常易读的查询分解为多个方法是人为地尝试修复可读性可能是一个问题的警告,但会增加类级别代码的复杂性。

答案 1 :(得分:1)

查询可以被破解(完全,而不是更复杂的真实查询:-))

IQueryable<atype> query = a;

IQueryable<btype> query2 = from a1 in query
                           join join b1 in b on a1.id1 equals b1.id1
                           select b1;

IQueryable<ctype> query3 = from b1 in query2
                           join join c1 in c on b1.id1 equals c1.id1
                           select c1;

每个都可以放在一个具有如下签名的方法中:

IQueryable<ctype> JoinQuery2(IQueryable<btype> query2)
{
    IQueryable<ctype> query3 = from b1 in query2
                               join join c1 in c on b1.id1 equals c1.id1
                               select c1;
    return query3;
}

类型的查询很容易被破解,因为在每次加入后您都会丢弃&#34; old&#34;类型(因此在query2末尾只有select b1,而不是select a1+b1)。如果你必须同时保留这两个对象,那么它是不可行的,因为你需要new { a1, b1 }这是一个匿名对象,不能在周围传递,因为它& #39;是一个匿名对象。

请注意,或许简单地将查询拆分为多个变量将解决您的NPR问题,因为分析器无法看到完整的方法链。

var query2 = from a1 in a
             join join b1 in b on a1.id1 equals b1.id1
             select b1;

var query3 = from b1 in query2
             join join c1 in c on b1.id1 equals c1.id1
             select c1;

这个的情况下,你甚至可以使用匿名对象,比如

var query1 = from a1 in a
             join join b1 in b on a1.id1 equals b1.id1
             select new { a1, b1 };

var query3 = from a1b1 in query2
             join join c1 in c on a1b1.b1.id1 equals c1.id1
             select new { a1b1.a1, a1b1.b1, c1 };

等等。