Enity Framework 4.1 - обновление базы данных за одну поездку - PullRequest
0 голосов
/ 04 июля 2011

Допустим, у меня есть этот код:

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

В основном, чтобы это работало, мне нужно для простоты предоставить SaveChanges в методе Update. Но когда у меня есть 4 таких метода в строке, и 34243 пользователя хотят обновить данные, я не думаю, что сохранение для каждого из 4 поездок было бы хорошей идеей.

Есть ли способ в EF4.1 отложить обновление базы данных в последний момент, в приведенном примере, или я вынужден сохранять детализацию для каждого метода?

EDIT: В целях разъяснения. Я пытался не вызывать SaveChanges во внешнем методе, а только один раз, когда изменения должны быть сохранены.

Я приведу реальный пример:

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

А сейчас:

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

В этом случае рейтинг пользователей не обновляется, пока я не позвоню в SaveChanges в PostScore

Ответы [ 3 ]

1 голос
/ 04 июля 2011

В вашем примере это выглядит так: PostScore и LikeDislike используют разные экземпляры контекста.Это источник вашей проблемы, и нет способа избежать вызова нескольких SaveChanges в этом случае.Вся операция - это единица работы, и поэтому она должна использовать один экземпляр контекста.Использование нескольких экземпляров контекста в этом случае неверно.

В любом случае, даже если вы вызовете одиночный SaveChanges, у вас все равно будет отдельное обращение к базе данных для каждой обновленной, вставленной или удаленной сущности, поскольку EF не поддерживает командупакетирование.

0 голосов
/ 04 июля 2011

Это не совсем решает всю мою проблему, но, по крайней мере, я могу использовать один экземпляр Context: с Ninject:

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

А затем конструктор:

private JamiContext _ctx;
    private IRepository<User> _usrRepo;
    public ScoreService(IRepository<User> usrRepo, JamiContext ctx)
    {
        _ctx = ctx;
        _usrRepo = usrRepo;
    }
0 голосов
/ 04 июля 2011

Способ отложить обновление базы данных до последнего момента - не вызывать SaveChanges до последнего момента.

Вы имеете полный контроль над этим кодом, и если ваш код вызывает SaveChanges после каждого обновления, то это нужно изменить.

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