2012-07-04 35 views
5

Tôi có một hàm sử dụng LINQ để lấy dữ liệu từ cơ sở dữ liệu và sau đó tôi gọi hàm đó trong một hàm khác để tổng hợp tất cả các thuộc tính riêng lẻ bằng cách sử dụng .Sum trên mỗi thuộc tính riêng lẻ. Tôi đã tự hỏi nếu có một cách hiệu quả để tổng hợp tất cả các thuộc tính cùng một lúc chứ không phải là gọi .Sum() trên mỗi tài sản cá nhân. Tôi nghĩ rằng cách tôi đang làm ngay bây giờ, là rất chậm (mặc dù chưa được kiểm tra).Cách hiệu quả để gọi .Sum() trên nhiều thuộc tính

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); 
    } 

Sửa

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; } 
    } 

Trả lời

6

IIRC bạn có thể làm tất cả các khoản tiền trong một đi (miễn là truy vấn được phiên dịch sang SQL) với

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

Điều này sẽ cung cấp cho bạn một đối tượng chứa tất cả các khoản tiền là thuộc tính riêng biệt.

+0

Cảm ơn Jon. Nhưng tôi nhận được 'NotSupportedException' tại' var sums ... '. nhưng nó không liên quan gì đến giải pháp của bạn. Bởi vì tôi đã thử nghiệm cách tôi đã làm nó và nó vẫn sẽ ném ngoại lệ này. Nó có liên quan gì đến phần 'IQueryable ' không? – SherCoder

+0

Và giải pháp của bạn khác với cách tôi đang làm. Tôi vẫn phải gọi .Sum() trên từng thuộc tính riêng lẻ. Cảm ơn – SherCoder

+0

@SherCoder: Về ngoại lệ, bạn sẽ phải cho chúng tôi biết chính xác loại 'IQueryable' mà bạn đang làm việc. Về cách này tốt hơn: tất cả các khoản tiền được thể hiện như một phần của cùng một cây biểu thức, do đó, lớp dịch SQL có thể kéo chúng ra chỉ trong một truy vấn. – Jon

0

Tôi đã tìm hiểu lý do vì sao nó đang ném NotSupportedException. Tôi đã học được rằng Linq to Entity không hỗ trợ các nhà xây dựng với các tham số, Vì vậy, đã xóa các nhà xây dựng và thực hiện các thay đổi trong truy vấn của tôi. Tôi là một lập trình viên C# người mới, vì vậy hãy cho tôi biết nếu giải pháp của tôi có thể được cải thiện, nhưng ngay bây giờ nó đang làm việc tốt.

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; 
} 
Các vấn đề liên quan