2012-01-18 31 views
7

Tôi có một tuyên bố LINQ mà sẽ bổ sung lên các giá trị của nhiều cột, mỗi đầu với 'HH' mặc dù có những cột khác có sẵn:Tuyên bố xấu xí LINQ, một cách tốt hơn?

//TODO Clean up this mess 
var query1 = (from e in Data 
       where e.SD == date 
       select e).Select(x => x.HH01 + x.HH16 + x.HH17 + x.HH18 + x.HH19 + x.HH20 + x.HH21 + x.HH22 + x.HH23 + 
             x.HH24 + x.HH25 + x.HH26 + x.HH27 + x.HH28 + x.HH29 + x.HH30 + x.HH31 + x.HH32 + 
             x.HH33 + x.HH34 + x.HH35 + x.HH36 + x.HH37 + x.HH38 + x.HH39 + x.HH40 + x.HH41 + 
             x.HH42 + x.HH43 + x.HH44 +x.HH45 + x.HH46 + x.HH47 + x.HH48 + x.HH49.GetValueOrDefault()+ 
             x.HH50.GetValueOrDefault()); 

return query1.FirstOrDefault(); 

Có cách nào để dọn dẹp này lên? Tôi phải làm rất nhiều biến thể của điều này (trong các phương pháp khác nhau) vì vậy nó sẽ rõ ràng ra rất nhiều 'fluff' nếu nó có thể được.

Ngoài ra tôi muốn gọi .GetValueOrDefault() trên mỗi cột, nhưng hiện tại tôi đã thực hiện việc này do sự lộn xộn ngoại trừ hai cột cuối cùng.

Đề xuất được đánh giá cao!

+0

Giá trị bạn phải thêm luôn giống nhau không? Vì vậy, luôn luôn HH01, HH16, HH17, ...? –

+0

Nhà cung cấp LINQ nào bạn đang sử dụng? – Oded

+0

@WouterdeKort: Tôi đoán là không, khi anh ta phải làm các biến thể ... – FarligOpptreden

Trả lời

2

Tôi đoán bạn có thể sử dụng Reflections cho việc này:

double GetHHSum<T>(T x) where T : class 
{ 
    double result = 0; 

    var properties = typeof(T).GetProperties(); 
    foreach (var property in properties) 
    { 
     if (property.Name.StartsWith("HH")) 
      sum += Convert.ToSingle(property.GetValue(x)).GetValueOrDefault(); 
    } 

    return result; 
} 

Và sau đó sử dụng nó như thế này:

return (from e in Data 
     where e.SD == date 
     select e).ToList().Select(x => GetHHSum(x)).FirstOrDefault(); 

Mã không được thử nghiệm

+1

Điều này sẽ không hoạt động, bởi vì nhà cung cấp không biết cách dịch 'GetHHSum' sang SQL. –

+0

Tôi đã chỉnh sửa câu trả lời của mình. Không phải nó sẽ không cố gắng dịch nó thành SQL, nhưng chỉ cần sử dụng phần mở rộng helper LINQ để chọn đúng thứ. –

+1

Nó sẽ hoạt động nếu bạn thay đổi 'List' thành' ToList'. –

2

Tôi có thể sai vì tôi không biết dữ liệu của bạn, nhưng có vẻ như với tôi rằng chúng không được chuẩn hóa hoàn toàn (các thuộc tính lặp đi lặp lại). Bạn có thể xem xét đến biểu mẫu thứ 3 bình thường - do đó tạo một/một số bảng riêng biệt sẽ chứa một giá trị theo hàng - và sau đó để nối 2 bảng trong truy vấn LINQ của bạn.

Truy vấn liên kết sẽ trông đẹp hơn nhiều và sau đó bạn có thể thay đổi trường HH mà không thay đổi truy vấn của mình.

+0

Dữ liệu không liên quan gì đến tôi, tôi chỉ có một bảng cơ sở dữ liệu (mà tôi không thể thay đổi hoặc sửa đổi theo bất kỳ cách nào) và phải trích xuất dữ liệu vì nó là –

+0

Không có gì trong mã được đăng cho thấy dữ liệu không được chuẩn hóa – Cosmin

+0

Cosmin: thực sự câu trả lời của tôi dựa trên rất nhiều giả định. những gì đã dẫn tôi là việc sử dụng thuật ngữ "cột" trong câu hỏi. Ngoài ra, với kinh nghiệm nó rất dễ dàng để nhận ra loại vấn đề và giải quyết chúng ở gốc (dữ liệu) – Skyp

1

Một đề xuất là cấu trúc lại mã ở trên để sử dụng chuỗi phương thức LINQ và lambdas (sở thích cá nhân), sau đó trích xuất lambda chọn vào một phương pháp riêng biệt. Ví dụ:

// Note select e and .Select(x => x..) is redundant. Only need one 
var query1 = Data.Where(e => e.SD == date).Select(SumOfHValues); 
return query1.FirstOrDefault(); 

// Note types are unclear in your question so I've put dummy placeholders 
private static QueryResultType SumOfHValues(YourInputClassType x) 
{ 
    // Nothing wrong with this syntactically, it will be faster than a 
    // reflection solution 
    // 
    // Algorithmic code tends to have this sort of look & feel. 
    // You could make it more readable 
    // by commenting exactly what the summation is doing and 
    // with a mathematical notation or link to documentation/web source 
    return x.HH01 + x.HH16 + x.HH17 + x.HH18 + 
      x.HH19 + x.HH20 + x.HH21 + x.HH22 + 
      x.HH23 + x.HH24 + x.HH25 + x.HH26 + 
      x.HH27 + x.HH28 + x.HH29 + x.HH30 + 
      x.HH31 + x.HH32 + x.HH33 + x.HH34 + 
      x.HH35 + x.HH36 + x.HH37 + x.HH38 + 
      x.HH39 + x.HH40 + x.HH41 + x.HH42 + 
      x.HH43 + x.HH44 + x.HH45 + x.HH46 + 
      x.HH47 + x.HH48 + 
      x.HH49.GetValueOrDefault() + 
      x.HH50.GetValueOrDefault() 
} 

Ngoài ra, nếu bạn muốn gọi GetValueOrDefault() trên mỗi tài sản HHxx, bạn có thể bọc nó trong chức năng trợ giúp thêm. điều này thực sự thích hợp với tùy chọn mã. Bạn thích cái nào hơn? Thấy .GetValueOrDefault() ở cuối mỗi quyền truy cập thuộc tính hay một hàm xung quanh nó? ví dụ.

return x.HH01 + x.HH16 + x.HH17 + x.HH18 

trở thành

return Get(x.HH01) + Get(x.HH16) + Get(x.HH17) + Get(x.HH18) ... 

private static HClassType Get(HClassType input) 
{ 
    return input.GetValueOrDefault(); 
} 

Cá nhân tôi sẽ chỉ đi với lệnh đang HHxx + HHyy của tôi trong các cột và gọi .GetValueOrDefault() trên mỗi một. Nếu nó được đặt trong một phương thức trợ giúp thì ít nhất nó chỉ được viết một lần, ngay cả khi nó dài dòng.

Trân trọng,

Các vấn đề liên quan