linq to sql, сделайте один вызов БД вместо трех - PullRequest
3 голосов
/ 05 февраля 2011

Привет, я вычисляю баллы пользователей на основе полученных ими голосов за отправленные ими сообщения, отправленных событий и комментариев, набравших баллы -

public int GetUserPoints(string userName)
{
    int? postPoints = db.Posts.Where(p => p.Aspnet_User.UserName == userName).Sum(b => (int?)b.UpVotes);
    int? eventPoints = db.Events.Where(p => p.Aspnet_User.UserName == userName).Sum(b => (int?)b.UpVotes);
    int? commentPoints = db.Comments.Where(p => p.Aspnet_User.UserName == userName).Sum(c => (int?)c.UpVotes - (int?)c.DownVotes);

    return (postPoints.HasValue ? postPoints.Value : 0) + (eventPoints.HasValue ? eventPoints.Value : 0) + (commentPoints.HasValue ? commentPoints.Value / 5 : 0);
}

Я делаю 3 отдельных звонка в БД для достижения этой цели. Могу ли я сделать это в одном?

Ответы [ 3 ]

5 голосов
/ 05 февраля 2011

Если вам действительно нужен только один вызов и вы все еще используете LINQ to SQL для построения запроса, вы можете использовать:

var sum = (from p in db.Posts where p.Aspnet_User.UserName == userName select p.UpVotes).Concat
                (from e in db.Events where e.Aspnet_User.UserName == userName select e.UpVotes).Concat
                (from c in db.Comments where c.Aspnet_User.UserName == userName select (c.UpVotes - c.DownVotes)).Sum()
2 голосов
/ 05 февраля 2011

Для чего-то подобного было бы хорошей идеей создать хранимую процедуру на вашем SQL Server, которая сделает все это за вас (объединяет таблицы, выбирает сообщения пользователя и т. Д.), А затем возвращает только те значения, которые вы необходимо.

Вы можете легко вызвать хранимый процесс из Linq-to-SQL и получить обратно результаты.

Вы не указали точную структуру таблицы, но, вероятно, это будет что-то вроде:

CREATE PROCEDURE dbo.GetUserPoints(@UserName VARCHAR(50))
AS BEGIN
   DECLARE @UserID UNIQUEIDENTIIFIER

   SELECT @UserID = ID FROM dbo.ASPNET_Users WHERE UserName = @UserName

   DECLARE @PostPoints INT
   DECLARE @EventPoints INT
   DECLARE @CommentPoints INT

   SELECT @PostPoints = SUM(ISNULL(Upvotes, 0)) 
     FROM dbo.Posts WHERE UserID = @UserID

   SELECT @EventPoints = SUM(ISNULL(Upvotes, 0))
     FROM dbo.Events WHERE UserID = @UserID

   SELECT @CommentPoints = SUM(ISNULL(Upvotes, 0)) - SUM(ISNULL(Downvotes, 0))
     FROM dbo.Comments WHERE UserID = @UserID

   -- updated: using RETURN gives you a method on your Linq context that you can
   -- easily call like this:
   --
   -- int myUserPoints = dataContext.GetUserPoints(......)
   --
   RETURN @PostPoints + @EventPoints + (@CommentPoints / 5)
END

, а затем добавьте эту хранимую процедуру в ваш Linq-to-SQL DataContext, и вы сможете вызывать этот хранимый процесс как метод в контексте данных, что-то вроде этого:

public int GetUserPoints(string userName)
{
    return db.GetUserPoints(userName);
}
1 голос
/ 05 февраля 2011

Одним простым способом было бы создать представление в вашей базе данных, которое выполняет все необходимые запросы / вычисления, а затем использовать L2S для запроса представления. Это приведет к одному вызову в вашей базе данных. Мы делаем это иногда, чтобы сэкономить на обращениях к базе данных и / или если наш запрос имеет особые потребности (например, подсказки блокировки и т. Д.) Использование представлений также является отличным способом гидратации специальных объектов домена (объектов, которые не имеют отношения 1: 1 к таблице в базе данных).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...