2014-02-09 35 views
1

假设我的SQL数据库中有三个表 - Users,Books和UsersBooks。使用多个连接和谓词优化LINQ查询

我正在寻找方法来优化Web方法的设计/性能,该方法采用用户名列表并返回包含用户及其书籍的JSON对象。我正在使用Linq2Entities和SQL Server 2008.

这个问题的动机是Web方法被称为很多(并且正在增长!),所以我需要找到让它运行更加精简和更加新颖的方法。

下面是当前设计的一个精简版:

private string MyWebMethod(string input) { 
    JavaScriptSerializer serializer = new JavaScriptSerializer(); 
    List<string> userNames = serializer.Deserialize<List<string>>(input); 

    using(var db = new dbContext()) { 
     var usersAndBooks = from u in db.Users 
          join ub in db.UsersBooks on u.UserId equals ub.UserId 
          join b in db.Books on ub.BookId equals b.BookId 
          select new Result { User = u, UsersBooks = ub, Book = b }; 

     var predicate = PredicateBuilder.False<Result>(); 

     // Construct predicate to filter usersAndBooks down to users we care about 
     foreach(var name in userNames) { 
      predicate = predicate.Or(r => r.User.UserName.Equals(name)); 
     } 

     usersAndBooks = usersAndBooks.AsExpandable().Where(predicate); 

     foreach(var name in userNames) { 
      // Logic to construct final {User:{Books}} JSON object 
     } 
    } 
} 

回答

3

为什么不直接使用.Contains

var usersAndBooks = from u in db.Users 
        where userNames.Contains(u.UserName) 
        join ub in db.UsersBooks on u.UserId equals ub.UserId 
        join b in db.Books on ub.BookId equals b.BookId 
        select new Result { User = u, UsersBooks = ub, Book = b }; 

我认为使用linqkit /谓词构建器/表达式访问者在这里是矫枉过正的。你基本上可以用LINQ .Contains做一个SQL IN子句。

它很容易为数据库优化这个:

WHERE User.UserName IN ('user1', 'user2', 'user3') 

...比这

WHERE User.UserName = 'user1' OR User.UserName = 'user2' OR User.UserName = 'user3' 

其次,是真的有必要遍历的结果?

foreach(var name in userNames) { 
    // Logic to construct final {User:{Books}} JSON object 
} 

...不知道的逻辑是什么在这里,但你可以使用转换只是一个。选择:

// Logic to construct final {User:{Books}} JSON object 
var finalOutput = usersAndBooks.Select(x => new ...); 

唯一的其他东西我可以推荐,比其他缓存或一些其他类型的快速数据传送服务的Redis的一样,使用替代JavaScriptSerializer Newtonsoft JSON.Net:

List<string> userNames = JsonConvert.DeserializeObject<List<string>>(input); 
+0

谢谢 - 总是尽量保持简单。从这些变化中没有看到明显的性能提升,但绝对是一种更清洁的设计 – djpark

+0

在这种情况下,我认为Pressacco的答案会对你更好。无论是制作自定义SQL查询还是预先计算数据并将其存储在可以快速获取到的位置。 – danludwig

2

如果性能是一个问题,看看实施缓存scenari o适合您的网站。 .net框架提供了多种缓存选项,并且有几种第三方解决方案可供选择。

此外,除了选择缓存技术,你也应该确定一个缓存策略(整个页面,仅仅是页面中的某些组件等)

的窍门是在绝对必要时只查询数据库。

缓存技术

补充阅读

+1

不要忘了redis! – danludwig