Εδώ και λίγο καιρό προσπαθώ να κάνω ένα μικρό παράδειγμα χρησιμοποιώντας το Entity Framework για την επικοινωνία με την βάση δεδομένων. Να πω ότι έχω μια σχετική εμπειρία με NHibernate γι αυτό και προτιμώ να δουλέψω με το code first αν και η ερώτησή μου μάλλον υπάρχει και στις άλλες μεθοδολογίες (model first, database first). Αυτό που θέλω να ρωτήσω είναι αν υπάρχει μια βέλτιστη λύση για το πως ανακτούμε ένα ολόκληρο object graph; Έχω δει αρκετά παραδείγματα αλλά δε νομίζω πως έχω πετύχει τον καλύτερο τρόπο. Για να γίνω πιο συγκεκριμένος θα παραθέσω αρκετό κώδικα που ελπίζω να κάνει τα πράγματα πιο κατανοητά.
Έχω τις εξής τρεις κλάσεις:
public class Field {
public virtual string Description { get; set; }
public virtual Region Region { get; set; }
public virtual IList<Crop> Crops { get; set;}
}
public class Region {
public virtual string Description {get; set; }
public virtual Region Parent {get; set; }
public virtual IList<Region> Children {get; set;}
}
public class Crop{
public virtual Field Field { get; set;}
public virtual CropKind Kind { get; set; }
}
Όπου σαν βασική οντότητα είναι η Field που έχει ένα property Region που είναι μια δενδρική δομή και επίσης έχει μια λίστα με πολλά crops που με την σειρά τους δείχνουν και αυτά σε μια άλλη κλάση τύπου CropKind που για λόγους συντομίας δεν την έγραψα. Αυτό που θέλω να μάθω είναι πως μπορώ να ανακτώ όλες τις συσχετίσεις όταν ανακτώ κάποιο συγκεκριμένο Field. Αυτό που κάνω τώρα είναι το εξής
public Field Retrieve(long id) {
using (var context = new FieldsContext("TestCodeFirst")) {
return context.Fields
.Include(field => field.Region)
.Include(field => field.Region.Parent)
.Include(field => field.Region.Children)
.Include(field => field.Region.Parent.Children)
.Include(field => field.Crops)
.Include(field => field.Crops.Select(crop => crop.Kind))
.Include(field => field.Crops.Select(crop => crop.Variety))
.Include(field => field.Crops.Select(crop => crop.Variety.Kind))
.FirstOrDefault(field => field.ID == id);
}
}
Κάνει αυτό που θέλω αλλά δεν μου φαίνεται σαν τον ιδανικό τρόπο. Βέβαια και στο επίσημο
blog του Entity Framework
αυτόν το τρόπο δείχνει. Μήπως μου διαφεύγει κάτι. Να παραθέσω και το configuration που τρέχει κατά την δημιουργία του context
public class FieldConfiguration : EntityTypeConfiguration<Field> {
public FieldConfiguration() {
this.Property(p => p.Description).HasColumnName(DataAccesConstants.DESCRIPTION_COLUMN_NAME);
this.HasOptional(p => p.Region).WithMany().Map(mc => mc.MapKey(FieldConstants.REGION_ID_COLUMN_NAME));
}
}
public class RegionConfiguration : EntityTypeConfiguration<Region> {
public RegionConfiguration() {
this.Property(p => p.Description).HasColumnName(DataAccesConstants.DESCRIPTION_COLUMN_NAME);
this.HasOptional(r => r.Parent).WithMany(r => r.Children).Map(mc => mc.MapKey(RegionConstants.PARENT_ID_COLUMN_NAME));
}
}
public class CropConfiguration : EntityTypeConfiguration<Crop> {
public CropConfiguration() {
this.HasRequired(p => p.Field).WithMany(c => c.Crops).Map(mc => mc.MapKey(CropConstants.FIELD_ID_COLUMN_NAME));
this.HasRequired(p => p.Kind).WithMany().Map(mc => mc.MapKey(CropConstants.CROPKIND_ID_COLUMN_NAME));
}
}
Βέβαια αυτό που έχω καταλάβει είναι ότι οι σχέσεις που ορίζεις σε αυτά τα configurations λαμβάνονται υπόψιν κυρίως για την δημιουργία της βάσης αν αυτή γίνεται από το Entity framework και όχι για την ανάκτηση των δεδομένων και στην συνέχεια την δημιουργία των αντικειμένων. Θα ήθελα τις συμβουλές σας και για την κυρίως ερώτηση αλλά και για ότι άλλο χωράει βελτίωση αλλαγή.
Σας ευχαριστώ προκαταβολικά.
My dream is to fly over the rainbow so high!!!!