假设我的SQL数据库中有三个表 - Users,Books和UsersBooks。
我正在寻找优化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
}
}
}
答案 0 :(得分: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 IN
。
.Contains
子句
数据库更容易优化:
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)之外,我可以推荐的唯一另一件事是使用Newtonsoft JSON.Net而不是JavaScriptSerializer:
List<string> userNames = JsonConvert.DeserializeObject<List<string>>(input);
答案 1 :(得分:2)
如果需要考虑性能,请查看实施适合您网站的缓存方案。 .net框架提供了几种缓存选项,有几种第三方解决方案可供选择。
此外,除了选择缓存技术之外,您还应该决定缓存策略(整个页面,只包含页面中的某些组件等)。
诀窍是只在绝对必要时才查询数据库。
CACHING TECHNOLOGIES
其他阅读