简体   繁体   中英

linq to sql, make one db call instead of three

Hi im calculating a users points based on upvotes they have recieved for posts they have submitted, events they have submitted and comments that have recieved points -

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);
}

Im making 3 separate db calls to achieve this. can i do this in one?

If you really need just one call and still use LINQ to SQL to build the query, you can use:

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()

For something like this, it would be a good idea to create a stored procedure on your SQL Server that does all that stuff for you (join the tables, select the user's posts and so forth) and then returns just the values you need.

You can easily call a stored proc from Linq-to-SQL and get back the results.

You didn't show the exact table structure, but it probably would be something like:

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

and then add this stored procedure to your Linq-to-SQL DataContext and you should be able to call that stored proc as a method on your data context, something like this:

public int GetUserPoints(string userName)
{
    return db.GetUserPoints(userName);
}

One easy way would be to create a view in your database that does all the queries/calculations you need and then use L2S to query the view. This would result in a single call to your database. We do this on occasion to save on calls to the database, and/or if our query has special needs (like lock hints etc...). Using views is also a great way to hydrate special domain objects (objects that don't have a 1:1 relationship to a table in the database).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM