Entity Framework 6.1 Обновление подмножества записи
У меня есть модель представления, которая инкапсулирует только некоторые из свойств модели базы данных. Эти свойства, содержащиеся в модели представления, являются единственными свойствами, которые я хочу обновить. Я хочу, чтобы другие свойства сохраняли свою ценность.
Во время моего исследования я нашел этот ответ, который, кажется, идеально подходит для моих потребностей, однако, несмотря на все мои усилия, я не могу заставить код работать так, как ожидалось.
Вот отдельный пример того, что я придумал:
static void Main() {
// Person with ID 1 already exists in database.
// 1. Update the Age and Name.
Person person = new Person();
person.Id = 1;
person.Age = 18;
person.Name = "Alex";
// 2. Do not update the NI. I want to preserve that value.
// person.NINumber = "123456";
Update(person);
}
static void Update(Person updatedPerson) {
var context = new PersonContext();
context.Persons.Attach(updatedPerson);
var entry = context.Entry(updatedPerson);
entry.Property(e => e.Name).IsModified = true;
entry.Property(e => e.Age).IsModified = true;
// Boom! Throws a validation exception saying that the
// NI field is required.
context.SaveChanges();
}
public class PersonContext : DbContext {
public DbSet<Person> Persons { get; set; }
}
public class Person {
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int Age { get; set; } // this is contrived so, yeah.
[Required]
public string NINumber { get; set; }
}
Что я делаю неправильно?
Ответы
Ответ 1
Вы основали свою работу над сообщением fooobar.com/questions/11942/..., но в другом потоке поля, которые не были изменены (и, как таковые, не были прикреплены модель) не были обязательными, и почему это сработало. Поскольку ваши поля необходимы, вы получите эту ошибку проверки.
Ваша проблема может быть решена с помощью решения проверки подлинности Framework с частичными обновлениями
Ответ 2
Это проверка, которая не позволяет сохранить ее. Вы можете отключить проверку с помощью context.Configuration.ValidateOnSaveEnabled = false;
, и она будет работать. Чтобы проверить конкретные поля, вы можете вызвать var error = entry.Property(e => e.Name).GetValidationErrors();
. Таким образом, вы, безусловно, можете сделать метод UpdateNameAndAge, который только обеспечивает соблюдение бизнес-правил и флагов этих свойств как измененных. Не требуется двойной запрос.
private static bool UpdateNameAndAge(int id, string name, int age)
{
bool success = false;
var context = new PersonContext();
context.Configuration.ValidateOnSaveEnabled = false;
var person = new Person() {Id = id, Name = name, Age = age};
context.Persons.Attach(person);
var entry = context.Entry(person);
// validate the two fields
var errorsName = entry.Property(e => e.Name).GetValidationErrors();
var errorsAge = entry.Property(e => e.Age).GetValidationErrors();
// save if validation was good
if (!errorsName.Any() && !errorsAge.Any())
{
entry.Property(e => e.Name).IsModified = true;
entry.Property(e => e.Age).IsModified = true;
if (context.SaveChanges() > 0)
{
success = true;
}
}
return success;
}
Ответ 3
(Отредактировано для ясности)
Контекст должен иметь полную копию объекта для обеспечения соблюдения бизнес-правил. Это может произойти только в том случае, если прикрепленный объект имеет все необходимые свойства, или частичный вид объединен с полной копией перед обновлением.
Я считаю, что то, что вы хотите сделать, концептуально невозможно: для таких обновлений потребуется либо сохраненная предварительно измененная копия, либо два запроса к базе данных, потому что бизнес-уровень нуждается в полной копии объекта для проверки.