2

我有一个复杂的查询,需要将其分解为不同的方法以满足 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);
4

2 回答 2

4

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

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

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

如果这不可能,我假设您使用的是 Visual Studio 2012 代码复杂性功能,这些功能不关注代码复杂性,而是关注IL复杂性。Linq 查询往往会在后台产生很多复杂性,这在代码中是不可见的。

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

于 2015-03-14T12:26:59.727 回答
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;
}

这种类型的查询很容易被破坏,因为在每次加入后你都会丢弃“旧”类型(所以在最后query2你只有select b1,没有select a1+b1)。如果您必须保留两个对象,那将是不可行的,因为您需要它是一个匿名对象,因为new { a1, b1 }它是一个匿名对象,所以它不能被传递。

请注意,也许简单地将查询拆分为多个变量将解决您的 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 };

等等。

于 2015-03-14T12:18:31.300 回答