IEntityChangeTracker错误的多个实例

时间:2012-05-01 17:42:07

标签: c# asp.net-mvc-3 ado.net

我已经阅读了至少十几个其他问题,就像这个问题一样,但我很难理解其中的一些问题。

我习惯于使用存储库和链接到实体框架的代码优先实体来开发ASP.NET MVC3。

我最近使用服务开发切换到数据库优先的ADO.NET。 我觉得这很干净,因为我可以通过我的外键访问东西。

无论如何,我的旧保存方法似乎已被破坏,因为我经常收到此错误

  

实体对象不能被多个实例引用   IEntityChangeTracker

所以这里看看我的保存操作和我的服务:

动作:

[HttpPost]
        public ActionResult AddReview(Review review, int id)
        {
            User loggedInUser = userService.GetUserByusername(User.Identity.Name);
            review.WriterId = loggedInUser.UserId;
            review.ProductId = id;

            if (ModelState.IsValid)
            {
                reviewService.Save(review);
                Product product = productService.GetProduct(id);

                if(product.Quantity>=1)
                    product.Quantity--;
                product.TimesBought++;

                productService.UpdateRating(product, reviewService);

                loggedInUser.GoldCoins -= product.Price;
                Session["goldCoins"] = loggedInUser.GoldCoins;
                userService.Save(loggedInUser);
                productService.Save(product);

            }
            else
            {
                return View(review);
            }
            return RedirectToAction("Index", "Answers", new { reviewId = review.ReviewId });

服务:

public class ReviewService : Service<Review, CapstoneEntities>
    {

        ...

        public void Save(Review review)
        {


        using (var db = new CapstoneEntities())
        {
            if (review.ReviewId == 0)
            {
                db.Reviews.Add(review);
                db.Entry(review).State = EntityState.Added;
            }
            else
            {
                db.Entry(review).State = EntityState.Modified;
            }
            db.SaveChanges();
        }
    }
}

我怀疑这行代码:使用(var db = new CapstoneEntities()),但我不确定如何做到这一点。再次,这与我以前的做事方式完美配合,但现在我在CRUD操作上遇到了错误。

谢谢。

2 个答案:

答案 0 :(得分:2)

看起来这是因为实体属于多个DataContexts。无论调用该操作的代码是什么,都应该使用相同的DataContext来创建实体,将其作为用于将其持久保存到数据存储区的实体。

在大多数情况下,您应该只保留一个DataContext实例。您可以使用像Castle这样的DI框架来定义/存储依赖项(在本例中为DataContext)作为Transient或PerWebRequest并将其注入服务和控制器,因此您将始终具有对DataContext的同一实例的引用。

答案 1 :(得分:2)

我是MVC&amp;的新手实体框架工作。经过多次战斗后,我遇到了同样的问题 这个解决方案对我有用。希望它对你们有用。

var mediaItem = db.MediaItems.FirstOrDefault(x => x.Id == mediaItemViewModel.Id);
    mediaItem.Name = mediaItemViewModel.Name;
    mediaItem.Description = mediaItemViewModel.Description;
    mediaItem.ModifiedDate = DateTime.Now;
    mediaItem.FileName = mediaItem.FileName;
    mediaItem.Size = KBToMBConversion(mediaItemViewModel.Size);
    mediaItem.Type = mediaItem.Type;

//db.Entry(mediaItem).State = EntityState.Modified;// coment This line
db.SaveChanges();

因为您正在从db读取整个对象并将其保存在当前上下文中,并且当您尝试修改实体状态时,它会告诉您已经有一个实体附加到当前上下文。只需调用保存更改就可以保存它。