使用Entity Framework更新现有条目

时间:2018-04-04 13:00:01

标签: c# asp.net sql-server entity-framework

我想用实体框架更新现有条目,这是我当前的代码:

[HttpPost]
public IActionResult Edit(Product product)
{
    if (ModelState.IsValid)
    {
        var result = _productRepository.Query().FirstOrDefault(x => x.Id == product.Id);

        if (result == null)
            return RedirectToAction("Index", "Products");

        _productRepository.Update(product);
        //result = product;
        _productRepository.Save();

        return View("Edit", result);
    }

我尝试了什么:

result = product;似乎没有更新db中的行。

public void Update(T item)
    {
        _context.Entry(item).CurrentValues.SetValues(item);
    }

似乎没有更新db中的行。

result.Title = product.Title - 有效,但是我必须为每个字段执行此操作,是否有办法仅通过将值替换为另一个对象来更新行?

1 个答案:

答案 0 :(得分:1)

修改

实际上,我意识到下面的代码不起作用,因为你已经跟踪了同一个实体,这是由这一行引起的:

 var result = _productRepository.Query().FirstOrDefault(x => x.Id == product.Id);

因此,您需要删除该行,只需使用下面的Update方法将product对象作为参数,或者使用结果对象并根据产品类中的数据进行更新,然后保存:

 result.Name = product.Name; 
 [...]

在这种情况下,您不需要致电_repository.update,只需_repository.save

使用产品进行更新

假设您的Product类是与您的Product实体类属于同一个类的对象,您需要确保它被实体框架跟踪并将其标记为已修改,然后才可以保存:

为此,请按以下步骤修改更新方法:

public void Update(T item)
{
    if (!_context.Set<T>().Local.Any(e => e == item))
    {
        _context.Set<T>().Attach(item);
    }
    _context.Entry(item).State = EntityState.Modified
}

然后保存它,它应该工作:

_productRepository.Update(product);
_productRepository.Save();

更好的方法?

您可以专门为视图创建一个模型类,然后根据需要检索和更新数据库实体模型,而不是在视图之间来回发送实体框架实体:

例如,如果您的Product数据库实体如下所示:

public class Product
{
    public int Id { get; set; }
    public string ProductName { get; set; }
    public int InternalId { get; set; }
}

在您看来,您不需要/想要使用InternalId字段,因此您的网站程序集中的模型可能如下所示:

public class ProductModel
{
    public int Id { get; set; }
    public string ProductName { get; set; }
}

然后在您的控制器中,这将是您将使用的:

[HttpPost]
public IActionResult Edit(ProductModel product)
{
    if (!ModelState.IsValid)
    {
        return View(product);
    }

    var dbProduct = _productRepository.Query().FirstOrDefault(x => x.Id == product.Id);

    if (dbProduct == null)
    {
        //Product doesn't exist, create one, show an error page etc...
        //In this case we go back to index
        return RedirectToAction("Index", "Products");
    }

    //Now update the dbProduct using the data from your model
    dbProduct.ProductName = product.ProductName;

如果你有很多字段,你不想手动执行此操作,有一些库会为你做这件事,例如,AutoMapper或我个人最喜欢的(更快,更容易使用)ValueInjecter

使用ValueInjecter,你会做这样的事情来自动分配所有公共属性

    dbProduct.InjectFrom(product);

最后,只需拨打保存,这次您不需要更改状态,因为EF已经在跟踪您的实体:

    _productRepository.Save();