2014-09-09 3 views
0

У меня есть объект, загруженный из одного DBContext с внесенными в него изменениями. Если я затем создаю другой DBContext, как бы я загрузил в него один и тот же объект из базы данных? Это должно быть общим для разных объектов, поэтому я не могу просто искать, где идентификаторы одинаковы - некоторые объекты могут иметь разные ключевые свойства.Open Entity в другом DBContext в Entity Framework

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


Редактировать

Я пытался сохранить это просто я думаю, что немного больше деталей требуется.

Скажет, у меня есть эта сущность:

public partial class SomeEntity : IValidatableObject 
{ 
    public int Id { get; set; } 

    public int StatusId { get; set; } 

    //... Other properties 

    public virtual ICollection<SomeOtherEntity> relatedEntity { get; set; } 

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext){ 
     // validation code 
    } 
} 

То, что я пытаюсь сделать, это когда объект заверил StatusId сравнивается с StatusId в настоящее время в базе данных и может произойти ошибка проверки - например, говорят StatusId не может быть изменен с 1 до 5. Как

Как Pawel упоминалось это может быть сделано с помощью OriginalValues ​​однако я также должен быть в состоянии проверить StatusId на основе значений в relatedEntity. Например, StatusId не может быть изменен с 1 на 2, если в relatedEntity существуют определенные значения.

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

Это немного грязный, но идея, которую я придумал это:

  • Сделать SomeEntity членом новой, пустой, интерфейс IMyValidationInterface.

    public interface IMyValidationInterface 
    { 
    } 
    
    public partial class SomeEntity : IValidatableObject, IMyValidationInterface 
    { 
        public int Id { get; set; } 
        // .... 
    } 
    
  • Override метод ValidateEntity на MyDBContext так, что объект с исходными значениями передается в метод проверки на сущность.

    public class MyDBContext : DbContext 
    { 
        protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items) 
        { 
         if (entityEntry.Entity is IMyValidationInterface) 
         { 
          var _validationContext = new MyDbContext(); 
    
          /// TODO: some code here to load a duplicated version of 
          ///  the entity from the database 
    
          var originalEntity; // unchanged entity is here 
    
          // unmodified entity is passed as an item to the entities 
          // Validate method 
          items.Add("OriginalEntity", originalEntity); 
         } 
    
         return base.ValidateEntity(entityEntry, items); 
        } 
    } 
    
    public partial class SomeEntity : IValidatableObject, IMyValidationInterface 
    { 
        // ..... 
    
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext){ 
         // validation code 
         if (validationContext.Items.ContainsKey("OriginalEntity")){ 
           var originalEntity = (SomeEntity)validationContext.Items["OriginalEntity"]; 
    
           // do validation here and yield return any validation errors 
         } 
        } 
    } 
    

бит я застрял на это TODO часть в приведенном выше фрагменте кода.

Я иду на это неправильно?

+0

Вы сохраняете изменения на ваш измененный объект загружен из первого DBC-контекста? –

+0

Возможно, вы можете использовать OriginalValues ​​и не должны иметь несколько контекстов? – Pawel

+0

Думаю, вам просто нужно знать, какие изменения внесены в сущность для проверки. Пожалуйста, проверьте эту ссылку, если это поможет, [LINK]: http://stackoverflow.com/questions/3265257/getting-all-changes-made-to-an-object-in-the-entity-framework – Ganesh

ответ

0

Быстро и грязно было бы сохранить исходное состояние, прежде чем изменять его в свое собственное свойство или поле, которое не отображается в базу данных, в идеале, когда оно загружается из базы данных.

interface IMaterializable 
{ 
    void OnMaterialized(); 
} 

class SomeEntity : IMaterializable, IValidatableObject 
{ 
    public int Id { get; set; } 

    public int StatusId { get; set; } 

    //... Other properties 

    public virtual ICollection<SomeOtherEntity> relatedEntity { get; set; } 

    int OriginalStatusId; 

    public void OnMaterialized() 
    { 
     OriginalStatusId = StatusId; 
    } 

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     // compare current status to original + related 
    } 
} 

А затем добавить этот обработчик к ObjectMaterialized события (см пример в this answer):

void OnObjectMaterialized(object sender, ObjectMaterializedEventArgs e) 
{ 
    var entity = e.Entity as IMaterializable; 

    if (entity != null) 
    { 
     entity.OnMaterialized(); 
    } 
} 
+0

Это мой план B. На самом деле я хотел бы убедиться, что у меня есть обновленная версия из базы данных перед сохранением. Потенциально «OriginalStatusId» может отличаться в базе данных, если он будет изменен кем-то еще после создания модели, но до ее сохранения. Загрузка его во время проверки приведет к снижению этого риска. – Rich

0

я закончил тем, что делал это в DataContext:

public class MyDBContext : DbContext 
{ 
    public virtual T GetEntityByPrimaryKey<T>(T entity) where T : class 
    { 
     var entityType = entity.GetType(); 
     var objectSet = ((IObjectContextAdapter)this).ObjectContext.CreateObjectSet<T>(); 
     var keyNames = objectSet.EntitySet.ElementType.KeyMembers.Select(edmMember => edmMember.Name); 
     var keyValues = keyNames.Select(name => entityType.GetProperty(name).GetValue(entity, null)).ToArray(); 

     return this.Set<T>().Find(keyValues); 
    } 

    protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items) 
    { 
     if (entityEntry.Entity is IMyValidationInterface) 
     { 
      var validationContext = new MyDBContext(); 

      var modifiedEntity = entityEntry.Entity; 

      var originalEntity = validationContext.GetEntityByPrimaryKey(a); 

      items.Add("OriginalEntity", originalEntity); 
     } 

     return base.ValidateEntity(entityEntry, items); 
    } 
} 

GetEntityByPrimaryKey был найден здесь Entity Framework Get Entity By Primary Key

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