2014-09-09 6 views
5

У меня есть модель оплаты с логическим значением «Status», значение которого по умолчанию равно false. После того, как платеж был сделан, мне нужно обновить статус «Статус» конкретного платежа до значения true.Обновление записи базы данных MVC Entity Framework

Вот код, который я пытался использовать для изменения конкретной записи в базе данных, но это просто не меняет его. Что я делаю не так?

Payment payment = new Payment(); 
payment = db.Payments.Find(orderId); 
db.Entry(payment).State = EntityState.Modified; 
payment.Status = true; 
db.SaveChanges(); 

Спасибо!

Это то, что в конечном итоге работает:

using (var con = new ApplicationDbContext()) 
{ 
    payment = con.Payments.First(x => x.Id == orderId); 
    payment.Status = true; 

    con.Payments.Attach(payment); 
    var entry = con.Entry(payment); 
    entry.Property(e => e.Status).IsModified = true; 
    con.SaveChanges(); 
} 
+0

Является ли db.Payments.Find (orderId), вы получаете платеж? –

+0

Да, orderId должен определить, какой платеж следует изменить (orderId совпадает с идентификатором платежа, который был создан при вводе платежной записи). – Pierre

+0

Какую версию рамки сущности вы используете? –

ответ

6
Payment payment = new Payment(); 
payment = db.Payments.Find(orderId); 
payment.Status = true; 
db.Entry(payment).State = EntityState.Modified; 
db.SaveChanges(); 
+0

просьба указать объяснения – webeno

+0

Забыл об этом сообщении, но это то, что я закончил с помощью: EDIT, обновит главный пост с моим кодом. – Pierre

1

Попробуйте это:

Payment payment; 
    using (var context = new DBContext()) //replace the name of your context 
    { 
     payment = context.Payments.Find(orderId); 
    } 

    if(payment != null) 
    { 
     payment.Status = true; 
    } 

    using (var context = new DBContext()) //replace the name of your context 
    { 
     context.Payments.Attach(payment); 
     context.Entry(payment).State = System.Data.EntityState.Modified;  
     context.SaveChanges(); 
    } 
+3

Почему вы создаете (и распоряжаетесь) два отдельных 'DbContexts' для этого простого обновления? – MEMark

+0

Полное обновление может быть выполнено в рамках одного контекста. Я написал это так, потому что я не знаю, работает ли он с прикрепленными объектами или с отсоединенным. Прикрепленные объекты требуют использования одного и того же контекста как для выбора обновления. –

+0

Все еще не работает. Возможно, проблема заключается в orderId. Я проверю, отправлен ли правильный orderId с веб-сайта платежа. Но единственная разница между нашим кодом - это строка кода с «Attach». Я никогда не использовал этот термин, также буду читать. Спасибо за ответ, отметит это как ответ, как только я разобрал эту проблему :) – Pierre

1

Как уже упоминалось here:

Метод Find на DbSet использует значение первичного ключа для попытайтесь найти объект, отслеживаемый контекстом. Если объект не найден в контексте, тогда запрос будет отправлен в базу данных, чтобы найти там объект. Null возвращается, если объект не найден в контексте или в базе данных.

Так что будьте уверены, что класс оплаты выглядит следующим образом:

public class Payment 
{ 
    [Key] 
    public int Id {get; set;} 
    public bool Status {get; set;} 
} 

И ваша запись сохранения логики может выглядеть следующим образом:

Payment payment = null; 
using (var ts = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1, 0, 0, 0))) 
{ 
    using (var context = new DBContext()) 
    { 
     context.Database.Log = s => { System.Diagnostics.Debug.WriteLine(s); }; 
     payment = context.Payments.Find(orderId); 
     if(payment != null) 
     { 
      payment.Status = true; 
      context.Entry(payment).State = System.Data.EntityState.Modified;  
     } 
     else 
     { 
      context.Payments.Add(new Payment(){ 
       Status = true 
      }); 
     } 
     context.SaveChanges(); 
    } 
    ts.Complete(); 
} 

Добавлена ​​область транзакции, чтобы убедиться, что он правильно открывать и закрывать, а также добавлять sql-запрос для отладки окна.

+0

Он все еще не меняет состояние платежа. Он достигает выражения «if», а не «else», но он не меняет состояние. OrderId верен, но он не обновляет этот платеж по какой-либо причине ... – Pierre

+0

Возможно, вы запускаете свой код в транзакции и не выполняете его? Попробуйте обернуть контекст db в TransactionScope, как показано в примере ниже. И проверьте SQL-запрос, который сгенерирован EF, используя его механизм ведения журнала. – aleha

3

Причина, по которой все эти ошибки терпят неудачу, заключается в том, что либо объект Payment никогда не привязан к DBContext, либо orderId на самом деле не совпадает с PK в таблице «Платежи». Чтобы на самом деле работать SaveChanges(), объект, который вы меняете, должен отслеживаться DBContext, а не только его EntityState, установленный на Modified. Также все эти примеры кажутся чрезмерно сложными.

using (var db = new DbContext()) 
{ 
    // make sure you have the right column/variable used here 
    var payment = db.Payments.FirstOrDefault(x => x.Id == orderId); 

    if(payment == null) throw new Exception("Invalid id: " + orderId); 

    // this variable is tracked by the db context 
    payment.Status = true; 

    db.SaveChanges(); 
} 
+0

Я проверил, что orderId действительно является правильным значением идентификатора платежа, который я хочу изменить. Я пробовал ваш код, но он все еще не обновляет эту запись. Если я заменил этот код «добавлением новой записи в Payment», тогда код будет работать нормально, поэтому код выполняет, но никаких изменений с обновлением записи не происходит. – Pierre

+0

@Pierre Какую версию Entity Framework вы используете? И этот код работает внутри транзакции на любом уровне? –

+0

Entity Framework: v4.0.30319. Я вообще не использую транзакции. – Pierre

0

Если вы просто иметь свой идентификатор объекта, просто сделать, как Али Golshani сказал. Но если у вас уже есть объект и просто хотите обновить, вы можете сделать так:

public void Update(Payment payment, int orderId) 
    { 
     //first find the entity to update 
     Payment oldEntity = DbSet.Find(orderId); 

     //detach this entity from the DbSet 
     Db.Entry(oldEntity).State = EntityState.Detached; 

     //set the state from the entity that you just received to modified 
     Db.Entry(obj).State = EntityState.Modified; 
    } 

Отсоединение избегает сообщение об ошибке: «Закрепление предприятие не удалось, так как другой объект того же типа уже есть один и тот же первичный ключ стоимость".

Я надеюсь, что это поможет.

Смежные вопросы