2015-08-21 18 views
14

Tôi đang lưu trữ một số dữ liệu bộ lọc trong bảng của mình. Hãy để tôi làm cho nó rõ ràng hơn: Tôi muốn lưu trữ một số mệnh đề where và giá trị của chúng trong cơ sở dữ liệu và sử dụng chúng khi tôi muốn lấy dữ liệu từ cơ sở dữ liệu.Dữ liệu bộ lọc khung thực thể theo chuỗi sql

Ví dụ, hãy xem xét một people bảng (thực thể thiết lập) và một số bộ lọc vào nó trong bảng khác:

"age" , "> 70" 
"gender" , "= male" 

Bây giờ khi tôi lấy dữ liệu từ bảng people Tôi muốn để có được các bộ lọc để lọc dữ liệu của tôi .

Tôi biết tôi có thể tạo truy vấn SQL dưới dạng chuỗi và thực thi điều đó nhưng có cách nào khác tốt hơn trong EF, LINQ không?

+0

Với khung thực thể, bạn có thể sử dụng Vị trí chức năng như thế này: ob.Where (p => p.age> 70 && gender == "male"). – MaticDiba

+0

độ tuổi và 70 là các bộ lọc chuỗi được lấy từ DB. Vậy làm thế nào tôi có thể viết dòng mã này?Đọc lại câu hỏi. cảm ơn. – ConductedClever

+0

Bạn có thể sử dụng [trình tạo biểu thức này] (http://www.codeproject.com/Tips/582450/Build-Where-Clause-Dynamically-in-Linq) –

Trả lời

8

Một giải pháp là sử dụng Dynamic Linq Library, sử dụng thư viện này bạn có thể có:

filterTable = //some code to retrive it 
var whereClause = string.Join(" AND ", filterTable.Select(x=> x.Left + x.Right)); 
var result = context.People.Where(whereClause).ToList(); 

Giả sử rằng bảng lọc có các cột LeftRight và bạn muốn tham gia các bộ lọc bằng AND.

Đề xuất của tôi là bao gồm thêm chi tiết trong bảng bộ lọc, ví dụ như tách các toán tử khỏi toán hạng và thêm cột xác định tham gia là And hoặc OR và cột xác định hàng khác tham gia. Bạn cần cấu trúc cây nếu bạn muốn xử lý các truy vấn phức tạp hơn như (A and B)Or(C and D).

Một giải pháp khác là xây dựng cây biểu thức từ bảng bộ lọc. Dưới đây là một ví dụ đơn giản:

var arg = Expression.Parameter(typeof(People)); 
Expression whereClause; 
for(var row in filterTable) 
{ 
    Expression rowClause; 
    var left = Expression.PropertyOrField(arg, row.PropertyName); 
    //here a type cast is needed for example 
    //var right = Expression.Constant(int.Parse(row.Right)); 
    var right = Expression.Constant(row.Right, left.Member.MemberType); 
    switch(row.Operator) 
    { 
      case "=": 
       rowClause = Expression.Equal(left, right); 
      break; 
      case ">": 
       rowClause = Expression.GreaterThan(left, right); 
      break; 
      case ">=": 
       rowClause = Expression.GreaterThanOrEqual(left, right); 
      break; 
     } 
     if(whereClause == null) 
     { 
      whereClause = rowClause; 
     } 
     else 
     { 
      whereClause = Expression.AndAlso(whereClause, rowClause); 
     } 
} 
var lambda = Expression.Lambda<Func<People, bool>>(whereClause, arg); 
context.People.Where(lambda); 

ví dụ này rất đơn giản, bạn nên thực hiện nhiều xác thực kiểu nhập và ... để làm việc này cho tất cả các loại truy vấn.

+3

Ví dụ của bạn sẽ giúp OP hình dung những gì cần phải làm. Hãy để tôi đề xuất điều gì đó cho độc giả quan tâm để tìm ra bước tiếp theo của họ: xem xét [mẫu thông dịch viên] (https://en.wikipedia.org/wiki/Interpreter_pattern) hoặc [mẫu khách truy cập] (https: //en.wikipedia .org/wiki/Visitor_pattern) ([so sánh] (http://www.researchgate.net/profile/Tijs_Van_der_Storm/publication/220878226_A_Case_of_Visitor_versus_Interpreter_Pattern/links/09e4150981f71beda3000000.pdf)). Điều này thường mang lại một thiết kế dễ bảo trì hơn, nhưng ý tưởng cũng giống như vậy. – tne

+0

Cả hai câu trả lời của bạn đều rực rỡ. nhưng tôi nghĩ tôi thích cái thứ hai hơn. Cảm ơn rất nhiều. – ConductedClever

+0

Bạn được chào đón. Điều thứ hai là khó khăn hơn, tôi xin chúc mừng bạn vì sự can đảm của bạn !! –

3

Đây là một câu hỏi thú vị. Trước hết, hãy đảm bảo bạn thành thật với chính mình: bạn đang tạo một ngôn ngữ truy vấn mới và đây là không một nhiệm vụ tầm thường (tuy nhiên có vẻ như các biểu thức tầm thường của bạn).

Nếu bạn chắc chắn mình không đánh giá thấp tác vụ, thì bạn sẽ muốn xem LINQ expression trees (reference documentation).

Thật không may, đó là một chủ đề khá rộng, tôi khuyến khích bạn tìm hiểu các khái niệm cơ bản và đặt câu hỏi cụ thể hơn khi chúng xuất hiện. Mục tiêu của bạn là diễn giải các biểu thức lọc của bạn (được lấy từ bảng của bạn) và tạo một cây biểu thức LINQ cho vị từ mà chúng đại diện. Sau đó, bạn có thể chuyển cây đến số Where() cuộc gọi như bình thường.

2

Mà không biết những gì UI của bạn trông giống như đây là một ví dụ đơn giản về những gì tôi đang nói về trong ý kiến ​​của tôi về Serialize.Linq thư viện

public void QuerySerializeDeserialize() 
    { 
      var exp = "(User.Age > 7 AND User.FirstName == \"Daniel\") OR User.Age < 10"; 
      var user = Expression.Parameter(typeof (User), "User"); 
      var parsExpression = 
        System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] {user}, null, exp); 

      //Convert the Expression to JSON 
      var query = e.ToJson(); 

      //Deserialize JSON back to expression 
      var serializer = new ExpressionSerializer(new JsonSerializer()); 
      var dExp = serializer.DeserializeText(query); 

      using (var context = new AppContext()) 
      { 
       var set = context.Set<User>().Where((Expression<Func<User, bool>>) dExp); 
      } 

    } 

Bạn có lẽ có thể nhận được fancier sử dụng phản xạ và gọi truy vấn chung LINQ của bạn dựa trên các loại đến từ biểu thức. Bằng cách này, bạn có thể tránh việc truyền các biểu thức như tôi đã làm ở phần cuối của ví dụ.

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