简体   繁体   中英

Entity Framework update based on database values?

Before Entity Framework, if I had something like a stock quantity or an on order quantity for a product, I would update it's quantities using the current database values as such:

UPDATE Products SET AvailableQty = AvailableQty - 2 WHERE ProductId = 1;

Is there a way to accomplish the same thing with Entity Framework? It seems like the framework follows a Load, Modify, Update pattern:

Product product = db.Products.FirstOrDefault(x => x.ProductId == 1);
product.AvailableQty += 2;
db.SaveChanges();

However, following this method there is a possibility that the product changes between the initial loading of the data and the update of the data. I know I can have a concurrency field on the entity that will prevent the update, but in most cases I don't want to have user intervention (such as a customer placing an order or receiving a purchase order).

Is there a preferred method to handling situations like these using EF, or should I just fall back to raw SQL for these scenarios?

Enclose your find and update within a transaction

using (var transaction = new System.Transactions.TransactionScope())
{
    Product product = db.Products.FirstOrDefault(x => x.ProductId == 1);
    product.AvailableQty += 2;
    db.SaveChanges();
    transaction.Complete();
}

"preferred method" would be opinion-based, so I'll just concentrate on the answer. EF allows you direct access to the database through the DbContext's Database property. You can execute SQL directly with ExecuteSqlCommand. Or, you can use the SqlQuery extension method.

ExecuteSqlCommand returns the records affected. And, the SqlQuery extension methods lets you use the fill provided by EF.

Also, if that is not enough power, you can create your own commands like this:

var direct = mydbContext.Database;
using (var command = direct.Connection.CreateCommand())
{
    if (command.Connection.State != ConnectionState.Open) 
    { 
        command.Connection.Open(); 
    }

    command.CommandText = query.ToString(); // Some query built with StringBuilder.
    command.Parameters.Add(new SqlParameter("@id", someId));
    using (var reader = command.ExecuteReader())
    {
        if (reader.Read()) 
        {
            ... code here ...
            reader.Close();
        }
        command.Connection.Close();
    }
}

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