2015-05-10 4 views
1

Сначала я использую код EF5.Как получить навигационное свойство внешнего ключа при вызове SaveChanges()?

У нас есть метод

LogHistoryTracking(DbEntityEntry entity) 

для входа изменений при SaveChanges называется.

В SaveChanges, мы получаем измененные объекты и переходят в LogHistoryTracking

var changedEntities = ChangeTracker.Entries().ToList(); 


Но когда я достигаю

changedEntity.OriginalValues.PropertyNames 

нет никаких свойств для внешних ключей не приемлю (только внешняя Id ключа - но как мы можем получить данные, когда здесь есть только id?).

Я также попытался найти решение для Google, но эта проблема может быть не столь популярной.

this article, но это не работает.

Цените любую помощь. Благодарю.

ответ

0

Если вы хотите, чтобы свойства вашей сущности были доступны, вы должны 'Include' их перед доступом к ним. Как и в следующем примере, который получает приказы первого Cutomer:

var orders = context.Customers 
    .Include("Orders") 
    .First().Orders; 

В этом примере, если вы не вызываете .Include("Orders") вы не будете иметь Customer.Orders. То же самое происходит, если у вас есть внешний ключ и забудьте указать свойство навигации внешнего ключа. Это связано с тем, что ключ (идентификатор) является частью объекта, а свойство навигации - нет.

Давайте посмотрим, один реальный пример:

public class Employee : Entity 
{ 
    public virtual int CompanyUserId { get; set; } 
    public virtual CompanyUser CompanyUser { get; set; } 
    //... cut out for brevity 
} 

Если вы получаете сотрудников, как это:

var employees = context.Employees; 

Вы не сможете сотрудникам доступа [0] .CompanyUser после контексте .SaveChanges() из-за ленивой загрузки. Соединение устанавливается после context.SaveChanges(), поэтому больше нет выборки данных.

Но если вы звоните:

var employees = context.Employees 
      .Include("CompanyUser") 
      .ToArray(); 

Вы сможете получить доступ к сотрудникам [0] .CompanyUser.SomeProperty сразу перед тем context.SaveChanges независимо отложенной загрузки, потому что ToArray() выполняет запрос и принести объекты с «включенными».

Если вы звоните:

var employees = context.Employees 
       .Include("CompanyUser"); 

Тогда вы будете иметь сотрудника [0] .CompanyUser.SomeProperty даже после того, как context.SaveChanges() с отложенной загрузки, потому что вы сказали EF включить свойство «CompanyUser» перед выполнением запрос. При выполнении EF будет включать именованное свойство.

ОБНОВЛЕНИЕ Перехват DbContext может быть выполнен как минимум двумя различными способами. Первый - переопределение SaveChanges() или SaveChangesAsync, потому что это виртуальная:

public class MyDbContext : DbContext 
{ 
    public event Action<MyDbContext> SavingChanges = _ => { }; 

    public override int SaveChanges() 
    { 
     this.SavingChanges(this); 
     return base.SaveChanges(); 
    } 
} 

Второй путь без прямого переопределение, скрывая DbContext внутри интерфейса, как этот (это из реального проекта):

public interface IUnitOfWork : IDisposable 
{ 
    void Commit(); 
} 

Третий способ (несколько отличается) является intercepting дБ вызовы. Четвертый способ существует, но это зависит от того, какой IoC вы используете. Если вы используете Castle Windsor, вы можете использовать interceptors. Я полагаю, что с каждым IoC есть свой способ перехватить это.

+0

Не могли бы вы уточнить, как добавить свойство навигации в объект? Сначала я использую код EF с ленивой загрузкой, поэтому я могу получить доступ к свойству навигации, но то, что я делаю, это метод переопределения SaveChanges() в DbContext. При этом методе мы можем только просмотреть объект DbEntityEntry, который является общим – NDC00629

+0

Извините, вы можете неправильно понять мой контекст. Я не говорю, что я буду LogHistoryTracking моим собственным кодом всякий раз, когда я использую SaveChanges(), чтобы сохранить что-то в базе данных. Я пытаюсь переопределить SaveChanges(), так что всякий раз, когда он вызывается, он автоматически добавляет новую запись для HistoryTracking. Вот почему я не могу указать, что я хочу в объект, потому что я не знаю для этого объекта то, что должно быть включено. Это общее. У меня только var changedEntities = ChangeTracker.Entries(). ToList(); и должны обрабатывать эти объекты как общие. – NDC00629

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