1

Я новичок в Code First, поэтому, пожалуйста, со мной. Вытащив волосы на целый день, пытаясь получить простой процесс, я прошу сообщество помочь.Мои коллекции/модель выглядят отлично после сохранения, но при загрузке объекта я не получаю данные обратно. Что я делаю не так?

Вот мой исходный код для моей модели:

public class User 
{ 
    public User() 
    { 
     GUID = Guid.NewGuid(); 
     Account = new Account(); 
     Location = new Location(); 
    } 

    public long UserID { get; set; } 
    public Guid GUID { get; set; } 
    public string DisplayName { get; set; } 
    public Location Location { get; set; } 
    public virtual Account Account { get; set; } 
} 

public class UserConfiguration : EntityTypeConfiguration<User> 
{ 
    public UserConfiguration() 
    { 
     HasKey(x => x.UserID); 
    } 
} 

[ComplexType] 
public class Location 
{ 
    [MaxLength(2)] 
    public string CountryCode { get; set; } 
    [MaxLength(2)] 
    public string StateCode { get; set; } 
    public string City { get; set; } 
} 

public class Account 
{ 
    public Account() 
    { 
     if (EmailAddresses == null) EmailAddresses = new Collection<EmailAddress>(); 
    } 

    [ForeignKey("User")] 
    public long AccountID { get; set; } 

    public ICollection<EmailAddress> EmailAddresses { get; set; } 

    public virtual User User { get; set; } 
} 

public class AccountConfiguration : EntityTypeConfiguration<Account> 
{ 
    public AccountConfiguration() 
    { 
     HasKey(x => x.AccountID); 
     HasMany(x => x.EmailAddresses).WithRequired(x => x.Account); 
    } 
} 

public class EmailAddress 
{ 
    [Key] 
    public string Email { get; set; } 

    public EmailTypes Type { get; set; } 

    public long AccountID { get; set; } 
    public virtual Account Account { get; set; } 
} 

public class EmailAddressConfiguration : EntityTypeConfiguration<EmailAddress> 
{ 
    public EmailAddressConfiguration() 
    { 
     HasKey(x => x.Email); 
     HasRequired(x => x.Account).WithMany(x => x.EmailAddresses).HasForeignKey(x => x.AccountID); 
    } 
} 

А вот мой Entity Класс:

public class MyEntities : DbContext 
{ 
    public MyEntities() 
    { 
     Database.SetInitializer<MyEntities>(new DropCreateDatabaseAlways<MyEntities>()); 
    } 

    public DbSet<User> Users { get; set; } 
    public DbSet<Account> Accounts { get; set; } 
    public DbSet<EmailAddress> EmailAddresses { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add(new UserConfiguration()); 
     modelBuilder.Configurations.Add(new AccountConfiguration()); 
     modelBuilder.Configurations.Add(new EmailAddressConfiguration()); 

     base.OnModelCreating(modelBuilder); 
    } 
} 

И, наконец, мой код, который работает в приложении тест консоли:

static void Main(string[] args) 
    { 
     var id = CreateUser(); 

     using (MyEntities db = new MyEntities()) 
     { 
      var a = db.Users.Find(id); 
      var b = a.Account.EmailAddresses; 
      var c = db.Accounts.Find(id); 
      var d = db.EmailAddresses.Where(x => x.Account.AccountID == id).ToList(); 
     } 

    } 

    private static long CreateUser() 
    { 
     using (MyEntities db = new MyEntities()) 
     { 
      var u = new User(); 
      u.DisplayName = "TEST"; 

      u.Location.CountryCode = "US"; 
      u.Location.StateCode = "HI"; 
      u.Location.City = "Kauai"; 

      EmailAddress e = new EmailAddress(); 
      e.Email = DateTime.UtcNow.Ticks + "@microsoft.com"; 
      e.Type = EmailTypes.Current; 

      u.Account.EmailAddresses.Add(e); 

      db.Users.Add(u); 

      var cnt = db.SaveChanges(); 
      // Here I get a return of the 4 entities saved, and my model looks correct. 

      return u.UserID; 
     } 
    } 

Как только модель была сохранена (CreateUser), я смог перемещаться по модели, и все выглядело идеально.

Проблема возникает, когда я пытаюсь извлечь данные обратно.
Мои переменные:

a - отправка по электронной почте adderess показывает 0 записей.

b - это тоже показывает 0 записей в коллекции.

c - переход на адрес электронной почты adderess показывает 0 записей.

d - здесь я могу получить адреса электронной почты (но не по навигации модели)

Пожалуйста, помогите!

ответ

0

Ваш тестовый код для доступа к свойствам навигации зависит от ленивой загрузки. Но ваша Account.EmailAddresses коллекции не помечена как virtual:

public ICollection<EmailAddress> EmailAddresses { get; set; } 

Навигация свойство должно быть virtual (как ваша User.Account собственности) для того, чтобы сделать отложенную загрузку возможно.

В качестве примечания: Я рекомендую, чтобы удалить экземпляр Account свойства навигации ...

Account = new Account(); 

... от User конструктора. Это известный источник неприятностей:

What would cause the Entity Framework to save an unloaded (but lazy loadable) reference over existing data?

EF 4.1 Code First: Why is EF not setting this navigation property?

Инстанцирование Location это прекрасно, потому что это сложный тип, а не навигационное свойство.

+0

Благодарю вас. Я добавил виртуальную коллекцию EmailAddresses и ничего не изменил. Я удалил 'Account = new Account();' и это, похоже, исправить проблему – user1265146

+0

@ user1265146: Это означает, что рабочее решение теперь удаляет 'Account = new Account()' ** AND ** 'virtual' collection, не так ли? Я не могу представить, что ваш код будет работать без 'virtual'. – Slauma

+0

Нет. Я просто удалил «Учетная запись = новая учетная запись()» и добавила виртуальные адреса электронной почты :) – user1265146