Стойност за актуализиране на DbContext рамка на обект без заявка и чрез външен ключ

Имам метод за актуализиране на някои таблици. За актуализация трябва да взема първо от TestProcess, но това не ми харесва. Как мога да актуализирам TestProcess без операция select(firstOrDefault), използвана само за операцията за актуализиране?

Пример за метод:

public void UpdateTestProcess(int id, string updateID)
{
    using (TestEntities context = new TestEntities())
                {
                    TestProcess pr = context.TestProcess.FirstOrDefault(x => x.MyID == id);
                    pr.UpdateID = updateID;             

                    context.TestProcess.Attach(pr);
                    context.ObjectStateManager.ChangeObjectState(pr, EntityState.Modified);
                    context.SaveChanges();
               }
}

person zrabzdn    schedule 02.07.2013    source източник
comment
Какво? За да актуализирате елемент, първо трябва да го „вземете“, за да приложите актуализациите. защо не ти харесва това   -  person Jonesopolis    schedule 02.07.2013
comment
Вероятно защото това е допълнителна заявка към базата данни   -  person Andrei    schedule 02.07.2013
comment
възможен дубликат на Мога ли да актуализирам EF обект без първо го търсите?   -  person Andrei    schedule 02.07.2013


Отговори (3)


TestProcess pr = new TestProcess()
{
    MyID == id,
};

context.Set<TestProcess>().Attach(pr);

pr.UpdateID = updateID;

context.SaveChanges();

Ако задавате стойността на стойността по подразбиране от този тип (например, задавайки int на 0), тя няма да бъде взета като промяна и трябва ръчно да зададете състоянието.

pr.UpdateID = updateID;
context.Entry(pr).Property(p => p.UpdateID).IsModified = true;

Можете да поставите такъв код в методи за разширение, така че можете да правите неща като това (ще оставя внедряването като упражнение):

Foo entity = this.DbContext.GetEntityForUpdate<Foo>(
    item => item.ID, model.ID
    );

this.DbContext.UpdateProperty(entity, item => item.Name, model.Name);
person user247702    schedule 03.07.2013
comment
Как да внедря вашия пример, ако използвах ObjectContext? - person zrabzdn; 03.07.2013
comment
Защо бихте използвали ObjectContext с EF 5? - person user247702; 03.07.2013
comment
В такъв случай не мога да ти помогна. DbContext се препоръчва от известно време, ако ситуацията го позволява, трябва да го използвате вместо това. - person user247702; 03.07.2013
comment
Във вашия пример MyID е първичен ключ. Имам нужда от актуализация не само чрез първичен ключ, но и от външен ключ. Ако използвах вашия пример с TestProcess pr = new TestProcess() { ForeignKey = id }; и pr.UpdateID = updateID; context.Entry(pr).Property(p =› p.UpdateID).IsModified = true; след това имам грешка Store update, insert, or delete statement засегна неочакван брой редове (0). Обектите може да са били променени или изтрити след зареждането на обектите. Обновете записа в ObjectStateManager. Мога ли да актуализирам с външен ключ? - person zrabzdn; 05.07.2013
comment
Не вярвам, че EF е в състояние да направи такава актуализация, без да му бъде предоставен първичният ключ. - person user247702; 05.07.2013

Можете да направите така (вероятно трябва да имате всички данни за тестовия процес):

TestProcess pr = new TestProcess();

pr.Id = id;
pr.UpdateID = updateID;

context.Attach(pr);
context.ObjectStateManager.ChangeObjectState(pr, EntityState.Modified);
context.SaveChanges();
person Andrei    schedule 02.07.2013
comment
Не е работа. Имам грешка: Аргумент 1: не мога да конвертирам от „Процес“ в „System.Data.Objects.DataClasses.IEntityWithKey“ - person zrabzdn; 02.07.2013
comment
Опитвам context.AttachTo(TestProcesses, pr); context.ObjectStateManager.ChangeObjectState(pr, EntityState.Modified); context.TestProcesses.MergeOption = MergeOption.OverwriteChanges; context.AcceptAllChanges(); Но не запазвайте промените - person zrabzdn; 03.07.2013

Кодът:

TestProcess testprocess = dbcontext.TestProcesses.Attach(new TestProcess { MyID = id });
tp.UpdateID = updateID;
dbcontext.Entry<TestProcess>(testprocess).Property(tp => tp.UpdateID).IsModified = true;
dbcontext.Configuration.ValidateOnSaveEnabled = false;
dbcontext.SaveChanges();

Резултатът TSQL:

exec sp_executesql N'UPDATE [dbo].[TestProcesses]
SET [UpdateID] = @0
WHERE ([MyID] = @1)
',N'@0 bigint,@1 bigint',@0=2,@1=1

Забележка:

Редът „IsModified = true“ е необходим, защото когато създавате новия обект TestProcess (само с попълнено свойство MyID), всички други свойства имат своите стойности по подразбиране (0, нула и т.н.). Ако искате да актуализирате DB със „стойност по подразбиране“, промяната няма да бъде открита от рамката на обекта и след това DB няма да бъде актуализирана.

В пример:

testprocess.UpdateID = null;

няма да работи без реда "IsModified = true", тъй като свойството UpdateID вече е null, когато сте създали празния обект TestProcess, трябва да кажете на EF, че тази колона трябва да се актуализира и това е целта на този ред.

person tecla    schedule 15.06.2017