2012-04-24 4 views
0

IValidatableObject.Validate только вызывается, когда объекты-исполнители DbEntityEntry.State отличаются от «Без изменений». И просто изменение свойства навигации не изменит состояние, и поэтому проверка не произойдет.IValidatableObject бесполезен для свойств навигации EF?

Почему Microsoft всегда выпускает полупрочные бета-версии?

Я не могу даже обнаружить навигации изменения свойств вручную:

var changes = context.ChangeTracker.Entries() 
    .Where(e => e.State != EntityState.Unchanged) 
    .ToArray(); 

Возвращает пустой массив.

ответ

5

Здесь есть несколько интересных моментов. EntityFramework отслеживает изменения свойств навигации независимо от изменений в объектах. context.ChangeTracker.Entries() возвращает только изменения сущностям, а не отношениям. Вот почему вы их не видите. Если вы действительно хотите посмотреть на отношения и как они изменились вы можете опуститься до ObjectContext и сделайте следующее:

var objectContext = ((IObjectContextAdapter) ctx).ObjectContext; 
foreach(var relationshipEntry in objectContext.ObjectStateManager 
               .GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted) 
               .Where(e => e.IsRelationship)) 
{ 
    EntityKey entityKey1, entityKey2; 

    if (relationshipEntry.State == EntityState.Added) 
    { 
     entityKey1 = (EntityKey)relationshipEntry.CurrentValues[0]; 
     entityKey2 = (EntityKey)relationshipEntry.CurrentValues[1];    
    } 
    else 
    { 
     entityKey1 = (EntityKey)relationshipEntry.OriginalValues[0]; 
     entityKey2 = (EntityKey)relationshipEntry.OriginalValues[1];       
    } 

    var entity1 = objectContext.GetObjectByKey((EntityKey)entityKey1); 
    var entity2 = objectContext.GetObjectByKey((EntityKey)entityKey2); 
} 

Сценарий, который более интересен для меня это один, когда вам нужно повторно подтвердить свой когда отношения изменяются. Я предполагаю, что у вас нет внешних ключей. В противном случае ваш объект был бы отмечен как измененный, так как изменение прав на навигацию изменило бы значение внешнего ключа, который, в свою очередь, помечал бы объект как измененный. В любом случае, учитывая, что у меня есть три действительных объекта - каков сценарий, в котором изменение отношений может привести к тому, что сущность (или модель) недействительна? Также обратите внимание, что валидация сама по себе является только подтверждением данного объекта, но никогда не следует свойствам навигации для проверки связанных объектов. Наконец, если вам действительно нужно проверить объекты, когда отношения меняются, я думаю, что у вас есть 4 варианта:

  • попробуйте добавить внешние ключи, так что изменение отношения изменит внешний ключ, который должен маркировать объект, как модифицированный (отказ от ответственности: я не пробовал это)

  • переопределить метод DbContext.ShouldValidateEntity() для проверки всех сущностей, а не только модифицированных (это происходит в случае логики фильтрации). Обратите внимание, что это может иметь некоторое негативное влияние на производительность. Вот код, вам нужно будет добавить в свой класс, производный от DbContext:

 protected override bool ShouldValidateEntity(DbEntityEntry entityEntry) 
     { 
      return (entityEntry.State & EntityState.Deleted) == 0; 
     } 
  • переопределение DbContext.SaveChanges(), так что вы вызываете проверку всех измененных образований и для всех лиц, которые связанные с измененными отношениями (используйте приведенный выше код, вы, скорее всего, заинтересованы только в добавленных позициях связей)

  • при изменении коллекции вручную отметьте объект как измененный. Обратите внимание, что это может привести к отправке ненужных обновлений в базу данных, чтобы в зависимости от того, сколько лиц вы отслеживаете это может быть намного дешевле просто проверить все, но удаленные объекты

Вы можете найти более подробную информацию о проверке и проверки настройки здесь : http://blogs.msdn.com/b/adonet/archive/2010/12/15/ef-feature-ctp5-validation.aspx http://blogs.msdn.com/b/adonet/archive/2011/05/27/ef-4-1-validation.aspx (Да, это для CTP и EF 4.1, но это имеет место)

+0

Что делать, если у меня много отношений?У меня есть правило бизнес/объект, в котором говорится: если логическое свойство A истинно, тогда сборник B не может быть пустым. Разве это не часть проверки уровня объекта? Должен ли я делать это в другом месте? – springy76

+0

BTW: теперь, когда он добавил внешние ключи, ObjectStateManager больше не возвращает никаких записей отношений (сам объект, точнее, свойства внешнего ключа теперь отмечены как измененные, как и ожидалось) – springy76

+0

1- * очень интересный сценарий в этом контексте. Причиной этого является то, что добавление и удаление объектов в коллекцию фактически не окажет никакого влияния на сущность на стороне «1» (то есть на принципале) - если вы посмотрите на базу данных, соответствующая таблица не будет иметь внешних ключей для так что он даже не знает, что они существуют. Однако в связанной таблице будут добавлены (или удалены) строки, которые будут иметь внешний ключ, указывающий на принципала (но не наоборот). Так был ли действительно изменен директор, если ни одно из значений не было изменено? – Pawel

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

  • Нет связанных вопросов^_^