Mes collections / modèle air fin après l'enregistrement, mais lors du chargement de l'entité que je n'ai pas les données en retour.Ce que je fais mal?
-
13-12-2019 - |
Question
Voici mon code source pour mon modèle:
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);
}
}
Et voici ma Classe d'Entité:
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);
}
}
Et enfin mon code qui s'exécute dans une console d'essai de l'application:
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;
}
}
Une fois que le modèle a été enregistré (CreateUser), j'ai pu naviguer dans le modèle et tout avait l'air parfait.
Le problème se pose lorsque j'essaie d'extraire les données de retour.
Mes variables:
un -- en naviguant à l'email adderess montre 0 enregistrements.
b -- cela aussi montre 0 enregistrements dans la collection.
c -- en naviguant à l'email adderess montre 0 enregistrements.
d -- ici je peux obtenir des adresses e-mail (mais pas par la navigation dans le modèle)
La solution
Votre code de test pour accéder aux propriétés de navigation s'appuie sur le chargement paresseux.Mais votre Account.EmailAddresses
la collection n'est pas marqué comme virtual
:
public ICollection<EmailAddress> EmailAddresses { get; set; }
Les propriétés de Navigation doit être virtual
(comme votre User.Account
propriété) afin de rendre le chargement différé possible.
Comme une note de côté:Je vous recommande de supprimer l'instanciation de l' Account
propriété de navigation...
Account = new Account();
...de l' User
constructeur.C'est une source connue de difficulté:
4.1 EF Premier Code:Pourquoi est-EF pas la définition de cette propriété de navigation?
L'instanciation d' Location
est bien parce que c'est un type complexe et non une propriété de navigation.