2017-07-24 4 views
0

J'ai cherché à peu près toutes les questions, tous les blogs ou toutes les documentations que j'ai pu trouver pour m'aider à répondre à cette question. Quelques-uns m'ont aidé à m'en rapprocher, mais je ne l'ai toujours pas résolu, car la plupart étaient dépassés ou pas vraiment à la hauteur de ce dont j'avais besoin. Ne vous embêtez pas à me parler d'Expressions, car si je devais emprunter la plus longue route, je n'utiliserais pas cette bibliothèque.Classement par propriété ICollection en utilisant son nom comme chaîne avec Dynamic Linq Library

Mon objectif de projet est de fournir le filtrage et l'ordonnancement en utilisant des méthodes génériques, en utilisant uniquement les chaînes de noms de tables/colonnes et les valeurs utilisées pour le filtrage. Longue histoire courte, j'ai deux tables, avec une relation de 1 à n, relié essentiellement comme ça et je veux commander par le nom du client:

public partial class Transactions{ 
    public ICollection<Customer> customer { get; set; }; 
} 

public partial class Customer{ 
    public string name { get; set; }; 
} 

Jusqu'à présent, je suis à peu près je besoin de réaliser ce que Je veux, sauf trouver comment structurer la chaîne OrderBy correctement, d'une manière que j'utiliserais un seul résultat ICollection.

Ce que j'ai à ce jour est à peu près comme ça (désolé d'être trop bavard sur ma documentation):

using System.Linq.Dynamic; 
using System.Reflection; 

namespace com.betha.common 
{ 
    public class Filter 
    { 
     /// <summary> 
     /// Dictionary of codenames and column names populated by a different, specific class (properties.Add("customer", "tb_customer.name")) 
     /// </summary> 
     public Dictionary<string, string> properties; 

     public Filter(Dictionary<string, string> properties) 
     { 
      this.properties = properties; 
     } 

     /// <summary> 
     /// Generic method designed to filter and order using just lists of column names and values 
     /// </summary> 
     /// <typeparam name="T">Type of the first IQueryable</typeparam> 
     /// <typeparam name="T2">Type of the second IQueryable</typeparam> 
     /// <param name="query">IQueryable containing the results from the parent table (context.table1).AsQueryable();</param> 
     /// <param name="query2">IQueryable containing a single result from a descendant table (context.table2.Select(t2 => t2.field).FirstOrDefault()).AsQueryable();</param> 
     /// <param name="prop">Property codename that if used, matches a properties codename Key</param> 
     /// <param name="descend">Condition for ascending or descending results</param> 
     /// <returns>Ordered and/or filtered IQueryable</returns> 
     public IQueryable<T> FilterandOrder<T, T2>(IQueryable<T> query, IQueryable<T2> query2, string prop = null, string descend = null) 
     { 
      if (!String.IsNullOrEmpty(prop)) 
      { 
       foreach (KeyValuePair<string, string> item in properties) 
       { 
        if (prop == item.Key) 
        { 
         prop = item.Value; 
        } 
       } 
       T2 subprop = query2.FirstOrDefault(); 

       if (prop.Contains(".")) 
       { 
        switch (prop.Split('.')) 
        { 
         default: 
          PropertyInfo property = subprop.GetType().GetProperty(prop.Split('.')[1]); 
          ParameterInfo[] index = property.GetIndexParameters(); 
          object value = subprop.GetType().GetProperty(prop.Split('.')[1]).GetValue(subprop, index); 

          //This is the main issue, I have pretty much everything I should need, but I can't imagine how to write this OrderBy string properly. 
          //If I were to do it without the library: table.OrderBy(t => t.table2.Select(t2 => t2.field).FirstOrDefault()); 
          //Without ordering by an ICollection property, like in the else below, string should look like: "field". 
          //Or in case of a 1 to 1 relationship, "table2.field". 
          query = DynamicQueryable.OrderBy(query, prop + (descend == "dec" ? " descending" : ""), value); 
          break; 
        } 
       } 
       else 
       { 
        query = DynamicQueryable.OrderBy(query, prop + (descend == "dec" ? " descending" : "")); 
       } 
      } 

      return query; 
     } 
    } 
} 
+0

est-ce que cela aide? https://stackoverflow.com/a/11001172/2557128 – NetMage

+0

Ce serait si je voulais décompiler la bibliothèque, faire ce changement et ensuite le perdre dès qu'une mise à jour de la bibliothèque est apparue. Mais merci de le suggérer. – Tiramonium

+0

Basé sur cet article, vous pouvez étendre la bibliothèque: https://blogs.msdn.microsoft.com/marcinon/2010/01/14/building-custom-linq-expressions-made-easy-with-dynamicqueryable/ – NetMage

Répondre

2

Vous pouvez remplacer le t => t.table2.Select(t2 => t2.field).FirstOrDefault() avec une fonction prise en charge, Min():

OrderBy("table2.Min(field)"); 
+0

Cela a fonctionné . Je ne peux toujours pas le croire. Été bloqué sur cela pour comme, 3 semaines maintenant. Je vous remercie. – Tiramonium

+0

Aussi, grâce à cela, je n'aurai même plus besoin de cette version surchargée de la méthode, avec 2 types génériques. Merci encore. – Tiramonium

+1

Heureux que cela a fonctionné. C'est trop dommage 'DynamicQuery' n'est pas un projet actif. – NetMage