4

J'espère que vous pourrez m'aider.Mappage de 2 tables à une seule entité dans Entity Framework

J'ai 2 tables dans le db: Bill et BillItem. Ces tableaux sont configurés avec un à une relation dans la db où le projet de loi est le tableau principe en BillItem est la personne à charge un

La structure du tableau Bill:

Int BillId (PK) 
Int BillTypeId Not Null 
Varchar(5) Usr Not Null 
DateTime Tm Not Null 

La structure de la table BillItem:

Int BillItemId (PK) 
Int ItemId Not Null 
Varchar(5) Usr Not Null 
DateTime Tm Not Null 

Je voudrais mapper ces tableau 2 en une seule classe POCO en utilisant l'API Fluent et Entity Framework 4.1 code de première approche

Je blême aussi t pour configurer les noms de colonnes de tables pour utiliser des noms de propriétés différents dans la classe POCO (c.-à-d. Id au lieu de BillId, User au lieu de Usr)

Il s'agit d'une base de données héritée, je ne peux modifier aucun de ses objets.

Comment y parvenir?

Merci à tous.

La classe résultante (si peut être):

public int Id {get;set;} 
public int BillTypeId {get;set;} 
public int ItemId {get;set;} 
public string User {get;set;} 
public string User1 {get;set;} 
public DateTime Tm {get;set;} 
public DateTime Tm1 {get;set;} 
+0

Quels sont les instances de votre classe POCO devraient aller à la table du projet de loi, et qui à la table BillItem? –

+0

Vous ne pouvez pas créer une vue? – ken2k

+0

@lazyberezovsky si cela est applicable alors la facture de classe devrait tenir toutes les propriétés des deux tables – Shpongle

Répondre

0

Pour les colonnes changement de nom, c'est facile:

[Table("SomeHorribleTableName")] 
    public class MyNiceTableName 
    { 
     [Column("Usr")] 
     public string User { get; set; } 
    } 

Ici, j'ai retitré l'entité ainsi .. pas besoin de Gardez un nom de table horrible. A propos de la cartographie 2 tables à 1 entité .. Je ne pense pas que ce soit possible. voir ici: Mapping data from 2 tables to 1 entity - Entity Framework 4

style fluide:

public class Bill 
    { 
     public int ID { get; set; } 
     public int BillTypeID { get; set; } 
     public string UserName { get; set; } 
     public DateTime Time { get; set; } 
    } 

    public class BillItem 
    { 
     public int ID { get; set; } 
     public int ItemID { get; set; } 
     public string UserName { get; set; } 
     public DateTime Time { get; set; } 
    } 

    internal class BillMap : EntityTypeConfiguration<Bill> 
    { 
     public BillMap() 
     { 
      ToTable("Bills"); 
      HasKey(x => x.ID); 
      Property(x => x.ID).HasColumnName("BillId"); 
      Property(x => x.BillTypeID).IsRequired().HasColumnName("BillTypeId"); 
      Property(p => p.UserName).IsRequired().HasColumnName("Usr"); 
      Property(x => x.Time).IsRequired().HasColumnName("Tm"); 
     } 
    } 

    internal class BillItemMap : EntityTypeConfiguration<BillItem> 
    { 
     public BillItemMap() 
     { 
      ToTable("BillItems"); 
      HasKey(x => x.ID); 
      Property(x => x.ID).HasColumnName("BillItemId"); 
      Property(x => x.ItemID).IsRequired().HasColumnName("ItemId"); 
      Property(p => p.UserName).IsRequired().HasColumnName("Usr"); 
      Property(x => x.Time).IsRequired().HasColumnName("Tm"); 
     } 
    } 

C'est probablement le meilleur que je peux faire. Pour ce qui est de la gestion de la colonne Usr dans les deux tableaux, vous devrez probablement traiter ce problème dans vos propres classes de contrôleur/couche logique métier.

une chose: pour les classes de configuration ci-dessus .. les appeler dans votre DbContext comme ceci:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Configurations.Add(new BillMap()); 
    modelBuilder.Configurations.Add(new BillItemMap()); 
} 
+0

J'utilise l'API Fluent stricte, pas d'annotations de données – Shpongle

+0

Dans ce cas, voir mon édition ci-dessus. – Matt

+0

La propriété de l'utilisateur provient de la table Bill. Mais qu'en est-il de la propriété User de la table BillItem? comment puis-je le mapper, et comment puis-je configurer cette propriété à partir de la table BillItem – Shpongle

0

Je pense que vous pouvez y parvenir avec la fonction Fractionnement Entité, mais vous aurez besoin d'utiliser certaines annotations de données (pas esacpe):
AVERTISSEMENT: Je n'ai pas essayé cette méthode, mais il pourrait fonctionner, vérifiez si vous aimez Première: annoter les propriétés qui appartiennent à la table BillItem en vous seul modèle de domaine clas s avec l'annotation de données HasColumnName.
Deuxième: Utilisez cet exemple de code

public class YourSingleModelClassNameConfiguration : EntityTypeConfiguration<YourSingleModelClassName> { 
    public YourSingleModelClassNameConfiguration() { 

     ToTable("Bill"); Property(param => param.Id).IsRequired().HasColumnName("BillId"); 

     // NOW REPEAT THAT FOR ALL BILL PROPERTIES WITH YOUR REQUIRED ATTRIBUTES (ISREQUIRED OR NOT, LENGTH ...) 

     // NOW THE PROPERTIES YOU NEED TO MAP TO THE BILL ITEMS TABLE GOES INTO THE MAP FUNCTION 
     Map(
     param => 
      { param.Properties(d => new {d.ItemId, d.User1}); m.ToTable("BillItem"); 
      } 
     ); 

     // DON'T FORGET TO MENTION THE REST OF THE PROPERTIES BELONGING TO THE BillItem TABLE INSIDE THE PROPERTIES METHOD IN THE LAST LINE. 

    } 
} 
0

pour cette question, vous pouvez le faire très facilement et vous avez 2 options. Le premier consiste à mapper les classes à l'aide du framework d'entité (mapping multiple tables to a single entity class in entity framework).La deuxième option est de le faire manuellement: La restriction que les 2 tables doivent suivre est que 1 doit être la table forte et la seconde doit être faible (en faisant cela, vous devriez avoir 1 seule par une seule de la table forte aux faibles) sinon, cela ne fonctionnera pas car le résultat sera une collection d'objets et vous devrez alors décider si le premier objet est celui dont vous avez besoin et pas d'autre.

si vous souhaitez utiliser une approche légèrement plus rapide que je recommande d'utiliser votre propre logique pour cartographier les objets POCO. créer 2 clases qui seront mappées avec la table de base de données et à partir d'un objet de service créer l'objet.

cette approche est bonne, car la requête LINQ résultant utiliser l'habitude qui rend INNER REJOINT plus rapidement. mais la jointure devrait être gardée de votre côté.

Exemple

int i=0; 
// this 2 refer to the 2 different mapped tables in your context database 
var pbdata = _pbdata.GetSingle(p=>p.StrongTableID == StrongTableID); 
var pb = _pb.GetSingle(p=>p.WeakTableID == pbdata.WeakTableID); 
// you can see that i am looking for the StrongTableID in order to select the entity value 

// this is optional but usefull! you can do the 
// "copy" inside a function where in future if the 
// object changes, you can update easily 
ObjectComposite.Map(body, ref pb, ref pbdata); 

// the following proccess needs to be done like this... 
// first save the value in the weak object so 
// the WeakTableID is recorded 
// UPDATE: maybe these 2 should go into a transact for more security... but... ok... 
Save(pb); 
i += this.unitOfWork.Save(); 
pbdata.ProfessionalBodyID = pb.ProfessionalBodyID; 

// once the values for the second objects are set, save it all again. 
Save(pbdata); 
i += this.unitOfWork.Save(); 
return i > 0 ? true : false; 

Cette approche est plus rapide, mais vous devez contrôler tout de vous. la bonne chose est que là, vous pouvez configurer autant de tables que vous voulez

espère que cela aide!

Questions connexes