Entity Framework
Scénarios de cartographie avancés: fractionnement d'entité, fractionnement de table
Recherche…
Introduction
Comment configurer votre modèle EF pour prendre en charge le fractionnement d'entité ou le fractionnement de table.
Fractionnement d'entité
Alors disons que vous avez une classe d'entité comme ceci:
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public string ZipCode { get; set; }
public string City { get; set; }
public string AddressLine { get; set; }
}
Et puis disons que vous voulez mapper cette entité Person en deux tables - une avec le PersonId et le Nom, et une autre avec les détails de l'adresse. Bien entendu, vous aurez également besoin du PersonId pour identifier la personne à laquelle appartient l’adresse. Donc, fondamentalement, vous voulez diviser l’entité en deux parties (voire plus). D'où le nom, entité fractionnée. Vous pouvez le faire en mappant chacune des propriétés sur une table différente:
public class MyDemoContext : DbContext
{
public DbSet<Person> Products { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>().Map(m =>
{
m.Properties(t => new { t.PersonId, t.Name });
m.ToTable("People");
}).Map(m =>
{
m.Properties(t => new { t.PersonId, t.AddressLine, t.City, t.ZipCode });
m.ToTable("PersonDetails");
});
}
}
Cela va créer deux tables: People et PersonDetails. Person a deux champs, PersonId et Name, PersonDetails a quatre colonnes, PersonId, AddressLine, City et ZipCode. Dans People, PersonId est la clé primaire. Dans PersonDetails, la clé primaire est également PersonId, mais il s'agit également d'une clé étrangère référençant PersonId dans la table Person.
Si vous interrogez le People DbSet, EF effectuera une jointure sur les PersonIds pour obtenir les données des deux tables afin de remplir les entités.
Vous pouvez également modifier le nom des colonnes:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>().Map(m =>
{
m.Properties(t => new { t.PersonId });
m.Property(t => t.Name).HasColumnName("PersonName");
m.ToTable("People");
}).Map(m =>
{
m.Property(t => t.PersonId).HasColumnName("ProprietorId");
m.Properties(t => new { t.AddressLine, t.City, t.ZipCode });
m.ToTable("PersonDetails");
});
}
Cela créera la même structure de table, mais dans la table People, il y aura une colonne PersonName au lieu de la colonne Name, et dans la table PersonDetails, il y aura un ProprietorId au lieu de la colonne PersonId.
Fractionnement de table
Et maintenant, disons que vous voulez faire le contraire du fractionnement d'entité: au lieu de mapper une entité en deux tables, vous souhaitez mapper une table en deux entités. Cela s'appelle le fractionnement de table. Disons que vous avez une table avec cinq colonnes: PersonId, Name, AddressLine, City, ZipCode, où PersonId est la clé primaire. Et puis vous souhaitez créer un modèle EF comme celui-ci:
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string ZipCode { get; set; }
public string City { get; set; }
public string AddressLine { get; set; }
public int PersonId { get; set; }
public Person Person { get; set; }
}
Une chose saute tout de suite: il n'y a pas de AddressId dans Address. En effet, les deux entités sont mappées sur la même table, elles doivent donc avoir la même clé primaire. Si vous divisez des tables, vous devez vous en occuper. Ainsi, outre le fractionnement de table, vous devez également configurer l'entité Address et spécifier la clé primaire. Et voici comment:
public class MyDemoContext : DbContext
{
public DbSet<Person> Products { get; set; }
public DbSet<Address> Addresses { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Address>().HasKey(t => t.PersonId);
modelBuilder.Entity<Person>().HasRequired(t => t.Address)
.WithRequiredPrincipal(t => t.Person);
modelBuilder.Entity<Person>().Map(m => m.ToTable("People"));
modelBuilder.Entity<Address>().Map(m => m.ToTable("People"));
}
}