2017-01-16 1 views
2

ich eine POCO-Klasse haben, die zwei Navigationseigenschaften hat, die wie folgt aussieht:Entity Framework, Stored Procedures und Navigationseigenschaften

public class Center : Archive 
{ 
    public int Id { get; set; } 
    [MaxLength(50)] public string ExternalId { get; set; } 
    [Required, MaxLength(150)] public string Name { get; set; } 
    [MaxLength(255)] public string Description { get; set; } 
    [MaxLength(50)] public string Address1 { get; set; } 
    [MaxLength(50)] public string Address2 { get; set; } 
    [MaxLength(50)] public string Address3 { get; set; } 
    [MaxLength(50)] public string Address4 { get; set; } 
    [MaxLength(10)] public string PostCode { get; set; } 

    [MaxLength(100)] public string CollectionPointContact { get; set; } 
    [MaxLength(50)] public string CollectionPointTelephone { get; set; } 
    [MaxLength(50)] public string CollectionPointFax { get; set; } 
    [MaxLength(255)] public string CollectionPointEmail { get; set; } 

    public int CompanyId { get; set; } 
    public Company Company { get; set; } 
    public IList<Collection> Collections { get; set; } 
} 

public class Company : Archive 
{ 
    public int Id { get; set; } 
    [Required, MaxLength(100)] 
    public string Name { get; set; } 
    public string Logo { get; set; } 
    [Required, MaxLength(50)] 
    public string Theme { get; set; } 

    public IList<User> Members { get; set; } 
    public IList<Center> Centers { get; set; } 
} 

public class Collection : Archive 
{ 
    public int Id { get; set; } 
    public int CenterId { get; set; } 
    [Required, MaxLength(50)] public string Reference { get; set; } 
    [MaxLength(255)] public string Description { get; set; } 
    [MaxLength(50)] public string CustomerReference { get; set; } 
    [MaxLength(100)] public string CustomerName { get; set; } 
    [MaxLength(100)] public string CustomerBusinessName { get; set; } 
    [MaxLength(100)] public string SupplierName { get; set; } 

    [Column(TypeName="Date")] public DateTime PlannedCollectionDate { get; set; } 
    public DateTime DeliveredDate { get; set; } 
    public DateTime CollectedDate { get; set; } 

    [MaxLength(100)] public string ReceivedBy { get; set; } 
    public string ReceivedBySignature { get; set; } 

    [MaxLength(100)] public string CollectedBy { get; set; } 
    public string CollectedBySignature { get; set; } 

    public CollectionStatus Status { get; set; } 
} 

Zuerst habe ich die Standard-träges Laden wurde mit den Eigenschaften zu füllen, aber es war Nehmen Sie 2s +, um 300 Datenzeilen (einschließlich der Eigenschaften) zu laden, was gerade nicht akzeptabel ist.

entschied ich mich eifrig Laden zu wechseln, weil ich mit dem eifrigen Laden kenne die SQL-Joins wird verwenden erzeugt, so würde theoretisch schneller sein. Dies war nicht der Fall, es dauerte immer noch etwa 2 Sekunden.

So war meine nächste Aufgabe zu versuchen, eine gespeicherte Prozedur zu verwenden. In meiner Repository Klasse schrieb ich eine generische Methode:

internal class Repository<T> : IDisposable, IRepository<T> where T : class 
{ 
    private readonly DatabaseContext _context; 
    private readonly DbSet<T> _dbEntitySet; 

    public Repository(DatabaseContext context) 
    { 
     if (context == null) throw new ArgumentNullException("context"); 
     _context = context; 
     _dbEntitySet = context.Set<T>(); 
    } 

    public IList<T> ExecuteStoredProcedure(string storedProcedureName, IList<SqlParameter> parameters = null) 
    { 
     if (parameters == null) 
      return _context.Database.SqlQuery<T>($"exec { storedProcedureName }").ToList(); 
     else 
      return _context.Database.SqlQuery<T>($"exec { storedProcedureName } @{ parameters[0].ParameterName }").ToList(); 
    } 
} 

Während diese schneller zu sein scheint (noch bei 1 s, die ich denke immer noch zu hoch ist), ist es nicht in meinen Navigationseigenschaften ziehen.

fand ich einen Artikel erklärt how to do it if you are not using generics aber ich möchte in der Lage sein, es für jede Navigationseigenschaft zu tun.

Ich dachte über Reflexion verwendet wird, aber das wird nur auf den Overhead-Kosten hinzu.

hat über diese und löste das Problem jemand kommen, oder gibt es einen besseren Weg, es zu tun?

+1

Ohne den Code, wie Sie ursprünglich Daten geladen haben, gibt es keine Möglichkeit festzustellen, ob es in einer performanten Weise getan wurde. Ich empfehle sehr selten Lazy Loading, da es in der Regel ein Performance-Albtraum ist. Beim Aufrufen einer gespeicherten Prozedur werden die Navigationseigenschaften nicht automatisch ausgefüllt, da EF die Abfrage nicht generiert. Wenn Sie die Sproc-Straße fortsetzen möchten, lassen Sie es mich wissen (ich habe gerade eine sehr erweiterte Abfrage, die ich verwendet habe, auf einen Proc umgestellt, weil EF keine performanten Abfragen für mich generiert hat). –

+0

In Ihrer [vorherigen Frage] (http://stackoverflow.com/q/41664805/861716) gesagt, dass Sie mit einer sehr geringen Menge von Daten zu tun hat. Zuallererst müssen Sie die korrekte Verwendung von Indizes analysieren, bevor Sie versuchen, zu optimieren, was nicht optimiert werden kann, wenn die Grundlage nicht stabil ist. Verwenden Sie Sql Server Management Studio, um die Abfrage mit "include actual query plan" auszuführen, und suchen Sie nach Indexhinweisen. * Dann * denke über die Daten nach, die du wirklich brauchst. Müssen Sie wirklich die vollständigen Aufzeichnungen zum Kunden bringen? * Projektionen * neigen dazu, die Leistung erheblich zu verbessern. –

Antwort

-1

Sie können das Eager- und Lazy-Laden kombinieren, indem Sie virtuelle Eigenschaften für die verzögerte Unterstützung verwenden, und die Include-Methode auf Ihrem IQeryable für Eager-Load-Related Entities aufrufen. Sie können die Leistung verbessern, indem Sie keine Tracking-Abfragen schreiben https://msdn.microsoft.com/en-us/data/jj556203 (Änderungen werden nicht von ef erkannt)

Verwandte Themen