0

Let's say I have this code:

class Score
{
     public Update(int score)
     {
         update score but do not call (context.SaveChanges())
     }
}

 class Foo
 {
     public DoSomething(int update)
     {
           Score score = new Score();
           score.Update(2);
           SomeObj obj = (select object);
           obj.Soo = 3;
           context.SaveChanges();
      }
 }

Basically to make it work, I need to explicity provide SaveChanges in method Update. But when I have 4 such methods in row, and 34243 users want to update data, I don't think saving for each one in 4 trips would be a good idea.

Is there way in EF4.1 to delay database update the last moment, in provided example, Or I'm forced to explicity save for each method ?

EDIT: For clarification. I tried to do not call SaveChanges in external method, and only one time where the changes mu be saved.

I will give an real example:

public class ScoreService : IScoreService
{
private JamiContext _ctx;
    private IRepository<User> _usrRepo;
    public ScoreService(IRepository<User> usrRepo)
    {
        _ctx = new JamiContext();
        _usrRepo = usrRepo;
    }

    public void PostScore(int userId, GlobalSettings gs, string name)
    {
        User user = _ctx.UserSet.Where(x => x.Id == userId).FirstOrDefault();
        if (name == "up")
        {
            user.Rating = user.Rating + gs.ScoreForLike;
        }
        else if (name == "down")
        {
            user.Rating = user.Rating - Math.Abs(gs.ScoreForDislike);
        }
    }
 }

And Now:

public PostRating LikeDislike(User user, int postId, int userId, GlobalSettings set, string name)
    {
        PostRating model = new PostRating();
        var post = (from p in _ctx.PostSet
                    where p.Id == postId
                    select p).FirstOrDefault();
        if (name == "up")
        {
            post.Like = post.Like + 1;
            model.Rating = post.Like - post.Dislike;
        }
        else if (name == "down")
        {
            post.Dislike = post.Dislike + 1;
            model.Rating = post.Like - post.Dislike;
        }

        PostVote pv = new PostVote();
        pv.PostId = post.Id;
        pv.UserId = user.Id;
        _ctx.PostVoteSet.Add(pv);
        _scoreSrv.PostScore(userId, set, name);
        _ctx.SaveChanges();

        return model;
   }

I this case user rating do not update, Until I call SaveChanges in PostScore

Łukasz Baran
  • 1,207
  • 2
  • 24
  • 43

3 Answers3

1

In your example it looks like PostScore and LikeDislike use different context instances. That is the source of your problem and there is no way to avoid calling multiple SaveChanges in that case. The whole operation is single unit of work and because of that it should use single context instance. Using multiple context instances in this case is wrong design.

Anyway even if you call single SaveChanges you will still have separate roundtrip to the database for each updated, inserted or deleted entity because EF doesn't support command batching.

Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654
0

The way to delay database update to the last moment is by not calling SaveChanges until the last moment.

You have complete control over this code, and if your code is calling SaveChanges after every update, then that needs changing.

Martin Booth
  • 8,079
  • 27
  • 30
0

This not really solves my entire problem, but at least I can use single instance of Context: With Ninject:

Bind<JamiContext>().To<JamiContext>().InRequestScope();

And then constructor:

private JamiContext _ctx;
    private IRepository<User> _usrRepo;
    public ScoreService(IRepository<User> usrRepo, JamiContext ctx)
    {
        _ctx = ctx;
        _usrRepo = usrRepo;
    }
Łukasz Baran
  • 1,207
  • 2
  • 24
  • 43
  • It is most probably only temporary and bad solution because context should never be singleton, static, shared or whatever else. Context should be used for single logical operation: http://stackoverflow.com/questions/3653009/entity-framework-and-connection-pooling/3653392#3653392 (context also isn't thread safe). – Ladislav Mrnka Jul 04 '11 at 10:34
  • So I'd rather should use .InRequestScope() then ? – Łukasz Baran Jul 04 '11 at 10:40