2017-05-09 14 views
0

我已經寫了Lambda表達式,完美適用於單個實體(客戶):編寫自定義lambda表達式對多個實體工作在LINQ

var property = typeof(Customer).GetProperty(inputArray[0], BindingFlags.Instance | BindingFlags.Public); 
var parameter = Expression.Parameter(typeof(Customer)); 
var memberExpression = Expression.Property(parameter, property); 
var eq = Expression.Equal(memberExpression, Expression.Constant(value)); 
//Combining eq with ANDs and ORs 
var lambdaExpression = Expression.Lambda<Func<Customer, bool>>(eq, parameter); 
var filteredCustomers = db.Customer.Where(lambdaExpression); 

但我有更多的實體,我需要寫一個組合查詢也會過濾這些實體。例如,我有一個Product實體,我想同時過濾產品和客戶。我怎樣才能改變上面的代碼,以便它可以與多個實體一起工作?提前致謝。

+0

您是否想同時過濾客戶和產品?或者您是否在尋找可以分別過濾兩個實體的方法? – nocodename

+0

什麼「同時過濾產品和客戶」的含義?像多線程「同時」或加入「在同一時間:) :) –

+0

@ArkadiuszRaszeja同時加入。 – jason

回答

1

基本上與我在here中發佈的相同。不同的是,我們將不得不檢索嵌套屬性的值。所以我們不再需要輸入字典中的PropertyValue,而是我們想要知道該屬性的Path是什麼。例如:CustomerProducts.Customer.UserID

然後,我們可以說路徑分成屬性的名稱的數組中的每個嵌套級,並建立這是一個從根對象(它是CustomerProducts在這種情況下)指向MemberExpression由我們想要最深屬性過濾集合。這裏的工作示例如下:

 // instead of passing pairs of PropertyName - PropertyValue 
     // we'll pass pairs of PropertyPath - PropertyValue 
     var filters = new Dictiontionary<string, object>(); 
     IEnumerable<CustomerProduct > query = listOfCustomerProducts; 

     // we will loop through the filters 
     foreach (var filter in filters) 
     { 
      // split property path by dot character 
      var propertyNames = filter.Key.Split('.'); 

      PropertyInfo property = null; 
      var parameter = Expression.Parameter(typeof(CustomerProduct)); 

      MemberExpression memberExpression = null; 

      // loop through all property names in path 
      foreach (var t in propertyNames) 
      { 
       // get correct property type 
       var type = property == null ? typeof(CustomerProduct) : property.PropertyType; 
       // find property in the given type 
       property = type.GetProperty(t, BindingFlags.Instance | BindingFlags.Public); 
       if (property == null) break; 

       // create member expression. 
       memberExpression = memberExpression == null 
        // if there isn't one, create new, using parameter expression 
        ? Expression.Property(parameter, property) 
        // if there already is one, use it to get into the nested property 
        : Expression.Property(memberExpression, property); 
      } 

      if (property == null) continue; 

      // Convert object type to the actual type of the property 
      var value = Convert.ChangeType(filter.Value, property.PropertyType, CultureInfo.InvariantCulture); 

      // Construct equal expression that compares MemberExpression for the property with converted value 
      var eq = Expression.Equal(memberExpression, Expression.Constant(value)); 

      // Build lambda expresssion (x => x.SampleProperty == some-value) 
      var lambdaExpression = Expression.Lambda<Func<CustomerProduct, bool>>(eq, parameter); 

      // And finally use the expression to filter the collection 
      query = query.Where(lambdaExpression.Compile()); 
     } 
+0

謝謝你的回答。但我想說的是將這兩個lambda表達式結合起來。例如,用戶可以這樣搜索:'(選擇UserID = 5和ProductName =「Banana」)'或'(選擇UserID = 5和ProductName =「Banana」或UserName =「Jason」)' – jason

+0

因此,我假設' UserID'是'Customer'的一個屬性。而'客戶'實體指的是'產品'實體中的一對多關係,意思是'客戶'具有一個屬性'ICollection '或類似的東西。而'Product'實體具有'ProductName'屬性。那是對的嗎? – nocodename

+0

其實和表格沒有關係。但是'Customer'具有'UserID','Product'具有'ProductName'(這些實體中有更多的屬性)。正如我所說,這些表格之間沒有關係,但我需要按照上述評論中的說法進行搜索。 – jason