2012-07-04 12 views
5

Mam funkcję, która używa Linq do pobierania danych z bazy danych, a następnie wywołuję tę funkcję w innej funkcji, aby zsumować wszystkie indywidualne właściwości przy użyciu .Sum na każdej pojedynczej właściwości. Zastanawiam się, czy istnieje skuteczny sposób na sumowanie wszystkich właściwości na raz, zamiast wywoływania .Sum() na każdej pojedynczej właściwości. Myślę, że sposób, w jaki teraz działam, jest bardzo powolny (choć nietestowany).Efektywny sposób wywoływania .Sum() na wielu właściwościach

public OminitureStats GetAvgOmnitureData(int? fnsId, int dateRange) 
    { 
     IQueryable<OminitureStats> query = GetOmnitureDataAsQueryable(fnsId, dateRange); 

     int pageViews = query.Sum(q => q.PageViews); 
     int monthlyUniqueVisitors = query.Sum(q => q.MonthlyUniqueVisitors); 
     int visits = query.Sum(q => q.Visits); 
     double pagesPerVisit = (double)query.Sum(q => q.PagesPerVisit); 
     double bounceRate = (double)query.Sum(q => q.BounceRate); 

     return new OminitureStats(pageViews, monthlyUniqueVisitors, visits, bounceRate, pagesPerVisit); 
    } 

Edit

private IQueryable<OminitureStats> GetOmnitureDataAsQueryable(int? fnsId, int dateRange) 
    { 
     var yesterday = DateTime.Today.AddDays(-1); 
     var nDays = yesterday.AddDays(-dateRange); 

     if (fnsId.HasValue) 
     { 
      IQueryable<OminitureStats> query = from o in lhDB.omniture_stats 
               where o.fns_id == fnsId 
                && o.date <= yesterday 
                && o.date > nDays 
               select new OminitureStats ( 
                o.page_views.GetValueOrDefault(), 
                o.monthly_unique.GetValueOrDefault(), 
                o.visits.GetValueOrDefault(), 
                (double)o.bounce_rate.GetValueOrDefault() 
               ); 
      return query; 
     } 
     return null; 
    } 

Edit:

public class OminitureStats 
    { 
     public OminitureStats(int PageViews, int MonthlyUniqueVisitors, int Visits, double BounceRate) 
     { 
      this.PageViews = PageViews; 
      this.MonthlyUniqueVisitors = MonthlyUniqueVisitors; 
      this.Visits = Visits; 
      this.BounceRate = BounceRate; 
      this.PagesPerVisit = Math.Round((double)(PageViews/Visits), 1); 
     } 

     public OminitureStats(int PageViews, int MonthlyUniqueVisitors, int Visits, double BounceRate, double PagesPerVisit) 
     { 
      this.PageViews = PageViews; 
      this.MonthlyUniqueVisitors = MonthlyUniqueVisitors; 
      this.Visits = Visits; 
      this.BounceRate = BounceRate; 
      this.PagesPerVisit = PagesPerVisit; 
     } 

     public int PageViews { get; set; } 
     public int MonthlyUniqueVisitors { get; set; } 
     public int Visits { get; set; } 
     public double PagesPerVisit { get; set; } 
     public double BounceRate { get; set; } 
    } 

Odpowiedz

6

IIRC można zrobić wszystkie sumy za jednym razem (dopóki kwerenda jest tłumaczona na SQL) z

var sums = query.GroupBy(q => 1) 
       .Select(g => new 
       { 
        PageViews = g.Sum(q => q.PageViews), 
        Visits = g.Sum(q => q.Visits), 
        // etc etc 
       }) 
       .Single(); 

To da ci jeden obiekt, który zawiera wszystkie sumy jako oddzielne właściwości.

+0

Dzięki Jon. Ale otrzymuję 'NotSupportedException' at' var sums ... '. ale nie ma to nic wspólnego z twoim rozwiązaniem. Ponieważ testowałem sposób, w jaki to robiłem, a on nadal rzuciłby ten wyjątek. Czy ma to coś wspólnego z częścią 'IQueryable '? – SherCoder

+0

A także, jak twoje rozwiązanie różni się od tego, co robię. Nadal muszę zadzwonić .Sum() na temat poszczególnych właściwości. Dzięki – SherCoder

+0

@SherCoder: w odniesieniu do wyjątku, będziesz musiał powiedzieć nam dokładnie, jakiego rodzaju 'IQueryable' używasz. Odnośnie tego, jak jest lepiej: wszystkie sumy są wyrażane jako część tego samego drzewa wyrażeń, więc warstwa tłumaczenia SQL może je wyciągnąć w jednym zapytaniu. – Jon

0

Dowiedziałem się, dlaczego rzuciłem NotSupportedException. Dowiedziałem się, że Linq to Entity nie obsługuje konstruktorów z parametrami, więc usunął konstruktorów i dokonał zmian w moim zapytaniu. Jestem początkującym programistą C#, więc daj mi znać, czy moje rozwiązanie może zostać ulepszone, ale od teraz działa dobrze.

public class OminitureStats 
{ 
    public int PageViews { get; set; } 
    public int MonthlyUniqueVisitors { get; set; } 
    public int Visits { get; set; } 
    public double PagesPerVisit { get; set; } 
    public double BounceRate { get; set; } 
} 


private IQueryable<OminitureStats> GetOmnitureDataAsQueryable(int? fnsId, int dateRange) 
{ 
    var yesterday = DateTime.Today.AddDays(-1); 
    var nDays = yesterday.AddDays(-dateRange); 

    if (fnsId.HasValue) 
    { 
     IQueryable<OminitureStats> query = from o in lhDB.omniture_stats 
              where o.fns_id == fnsId 
               && o.date <= yesterday 
               && o.date > nDays 
              select new OminitureStats() { 
               o.page_views.GetValueOrDefault(), 
               o.monthly_unique.GetValueOrDefault(), 
               o.visits.GetValueOrDefault(), 
               (double)o.bounce_rate.GetValueOrDefault() 
              }; 
     return query; 
    } 
    return null; 
} 
Powiązane problemy