简体   繁体   中英

Why should we attach model before update in Entity Framework?

I have question about the change tracker in Entity Framework. I read the change tracker document on MSDN - it said that if you insert a model into a database, its status in context will be Added , and when you execute SaveChanges() , it inserts a new row into the database and its status becomes unchanged .

So why should we attach a model before updating it in Entity Framework?

public virtual void Update(TEntity entity)
{
    _dbset.Attach(entity); => ???
    _context.Entry(entity).State = EntityState.Modified;
    _context.SaveChanges();
}

Update :

我的项目结构

我在存储库中的代码

While an entity is altered within the scope of a DbContext, and was not loaded /w AsNoTracking , the change tracker for that DbContext will pick up changes and apply updates when you call SaveChanges . As in the example you've given, in many cases you might be dealing with an Entity that currently isn't tracked by a DbContext anymore.

As a simple example: (Tracked entities)

public void UpdateDescription(int orderId, string description)
{
    using (var context = new AppDbContext())
    {
        var order = context.Orders.Single(x => x.OrderId == orderId);
        order.Description = description;
        context.SaveChanges();
    }
}

In this example, the Order entity is loaded, tracked, and updated within the scope of a single DbContext. Instead, if we have a method structure like this:

public Order GetOrderById(int orderId)
{
    using (var context = new AppDbContext())
    {
        return context.Orders.Single(x => x.OrderId == orderId);
    }
}

public void UpdateOrder(Order order)
{
    using (var context = new AppDbContext())
    {
        context.Attach(order);
        context.Entity(order).State = EntityState.Modified;
        context.SaveChanges();
    }
}

Such as in the case of web applications where an Edit page retrieves an Order entity and passes that to a view. When the user updates some fields on the page Model and submits, a separate Update call is made passing the model. With the "GetOrderById" call, the Order entity was loaded by one instance of the DbContext. When the "UpdateOrder" call occurs, that Order is effectively a deserialized POCO, not a tracked entity anymore. This would be why you need to attach it to the DbContext instance that Update will be using, and set it's entity state to Modified in order for EF to treat it as an entity that needs to be updated.

It is worth noting that in the first tracked example, the UPDATE SQL statement will effectively be something like:

UPDATE Orders SET Description = 'newDescription' WHERE OrderId = 1

where in the second example, the UPDATE statement would be more like:

UPDATE Orders SET OrderNumber = 21, CustomerId = 12, Description = 'newDescription' /* + all fields/FKs in Order table... */ WHERE OrderId = 1 

By attaching and setting an entity state to Modified, EF will update all non-PK properties on the entity, even if you only intend/expect for one field to have been modified. In the case of a web application, passing entities back to a controller to be updated this way can leave your system vulnerable to data tampering. (Changing fields/FKs that your UI did not allow) It also means you need to pass a complete entity all of the time to avoid data possibly getting wiped unexpectedly which increases the message payload size going back and forth between client and server.

Because EntityFramework only changed entities that exist in ChangeTracker .

And when you Attaching an entity to DbContext , entity framework know that one entity has tracked and maybe contains changes and apply changes in DataBase after SaveChanges .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM