实体类型"BookLoan"的实例无法跟踪 [英] The instance of entity type 'BookLoan' cannot be tracked

查看:71
本文介绍了实体类型"BookLoan"的实例无法跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试更新实体,但遇到以下错误:

I'm trying to update an entity and I've run into the following error:

InvalidOperationException:实体类型'BookLoan'的实例无法跟踪,因为此类型的另一个实例具有相同的密钥已被跟踪.添加新实体时,对于大多数关键如果没有设置键,则将创建一个唯一的临时键值(即,如果为key属性分配了其类型的默认值).如果要为新实体明确设置键值,请确保它们不要与现有实体或生成的临时值冲突对于其他新实体.附加现有实体时,请确保只有一个具有给定键值的实体实例附加到上下文.

InvalidOperationException: The instance of entity type 'BookLoan' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.

我进行了一些研究,可以看出,当我使用 _context.Update(bookloan); 时,我显然试图跟踪一个已经跟踪的实体,但是我并不是真的确定该怎么办.

I've done a little research and from what I can tell I'm apparently trying to track an already tracked entity when I use _context.Update(bookloan); but I'm not really sure what to do.

我想做的是更新数据库中的现有实体/记录.这里是get和post控制器,因为我不确定还要共享什么.

What I'm trying to do is update an existing entity/record in my database. Here are the get and post controllers as I'm not sure what else to share.

获取

    [HttpGet]
    public async Task<IActionResult> Return(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        if (isBookCheckedOut(id) == false)
        {
            //Not checked out
            return RedirectToAction("Index");
        }
        else
        {
            var bookloan = (from book in _context.Books.Where(b => b.BookId == id)
                        join loan in _context.BookLoans.Where(x => !x.ReturnedOn.HasValue) on book.BookId equals loan.BookID into result
                        from loanWithDefault in result.DefaultIfEmpty()
                        select new BookReturnViewModel
                        {
                            BookLoanID = loanWithDefault.BookLoanID,
                            BookID = book.BookId,
                            Title = book.Title,
                            StudentID = loanWithDefault == null ? null : loanWithDefault.StudentID,
                            StudentFristName = loanWithDefault == null ? null : loanWithDefault.Student.FirstName,
                            StudentLastName = loanWithDefault == null ? null : loanWithDefault.Student.LastName,
                            //Fines
                            CheckedOutOn = loanWithDefault == null ? (DateTime?)null : loanWithDefault.CheckedOutOn,
                            IsAvailable = loanWithDefault == null,
                            AvailableOn = loanWithDefault == null ? (DateTime?)null : loanWithDefault.DueOn
                        }).FirstOrDefault();

            if (bookloan == null)
            {
                return NotFound();
            }

            return View(bookloan);
        }
    }

帖子:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Return(BookReturnViewModel model)
    {


        if (ModelState.IsValid && isBookCheckedOut(1) == true)
        {
            var bookloan = new BookLoan()
            {
                BookLoanID = model.BookLoanID,
                BookID = model.BookID,
                StudentID = model.StudentID,
                CheckedOutOn = (DateTime)model.CheckedOutOn,
                DueOn = (DateTime)model.AvailableOn,
                ReturnedOn = DateTime.Now
            };


            try
            {

                _context.Update(bookloan);
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {

            }

            return RedirectToAction("Index");
        }
        else
        {

        }

        return View();
    }

推荐答案

您的上下文已经包含该实体,因此创建一个新实体,根据该实体的ID获取现有实体并更新其属性,然后保存它

Your context already includes the entity, so rather that creating a new one, get the existing one based on the ID of the entity and update its properties, then save it

if (ModelState.IsValid && isBookCheckedOut(1) == true)
{
    // Get the existing entity
    BookLoan bookLoan = db.BookLoans.Where(x => x.BookLoanID == model.BookLoanID).FirstOrDefault();
    if (bookLoan != null)
    {
        bookLoan.BookID = model.BookID;
        bookLoan.StudentID = model.StudentID;
        .... // update other properties as required
        _context.Update(bookloan);
        await _context.SaveChangesAsync();
        return RedirectToAction("Index");
    }
    ....

旁注:返回视图时,使用 return View(model); 传递模型的一种很好的做法-即使您不这样做,表单控件也将正确填充(因为它们不正确)从 ModelState 获取值,但是如果您对模型属性有任何引用(例如÷ div @@ Model.someProperty</div> ),则会抛出一个

Side note: when returning the view, its good practice to pass back the model using return View(model); - your form controls will be correctly populated even if you don't (because they take the values from ModelState), but if you have any references to the model properties (e.g. <div>@Model.someProperty</div>) it would throw an exception.

这篇关于实体类型"BookLoan"的实例无法跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆