2009-09-24 7 views
2

Ok, j'ai trouvé this, ce qui me permettra de le faire:LINQ to Sql - Pattern Repository - Dynamic OrderBy

public IList<Item> GetItems(string orderbyColumn) 
{ 
    return _repository.GetItems().OrderBy(orderByColumn).ToList(); 
} 

Est-ce la meilleure façon de faire la commande "dynamique"? Je veux être capable de passer le nom de la colonne sous la forme d'une chaîne (et la direction de tri) à mon service, et de l'ordonner de la manière correcte.

Répondre

1

Si vous êtes juste après le tri dynamique sans systeme complet dynamique-Linq, vous pouvez consulter un poste que j'ai écrit à ce sujet un certain temps: click

EDIT: Je ne sais pas plus vraiment un blog alors voici la méthode d'extension réelle:

public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string sortExpression) where TEntity : class 
    { 
     if (string.IsNullOrEmpty(sortExpression)) 
      return source; // nothing to sort on 

     var entityType = typeof(TEntity); 
     string ascSortMethodName = "OrderBy"; 
     string descSortMethodName = "OrderByDescending";    
     string[] sortExpressionParts = sortExpression.Split(' '); 
     string sortProperty = sortExpressionParts[0]; 
     string sortMethod = ascSortMethodName; 

     if (sortExpressionParts.Length > 1 && sortExpressionParts[1] == "DESC") 
      sortMethod = descSortMethodName;  

     var property = entityType.GetProperty(sortProperty); 
     var parameter = Expression.Parameter(entityType, "p"); 
     var propertyAccess = Expression.MakeMemberAccess(parameter, property); 
     var orderByExp = Expression.Lambda(propertyAccess, parameter); 

     MethodCallExpression resultExp = Expression.Call(
              typeof(Queryable), 
              sortMethod, 
              new Type[] { entityType, property.PropertyType }, 
              source.Expression, 
              Expression.Quote(orderByExp)); 

     return source.Provider.CreateQuery<TEntity>(resultExp); 
    } 
+0

Semble que l'entrée de blog est un lien mort. @ ray2k ... pouvez-vous le mettre à jour? –

+0

Terminé. http://blog.invalidoperation.com/2011/07/linq-to-sql-and-objectdatasource-bff.html – ray2k

+0

On dirait que le nouveau lien est mort aussi. Pourriez-vous republier la solution ici dans votre réponse? – jahu

9

C'est certainement un moyen viable de faire du tri dynamique. Ch00k fourni une autre option dans his answer à this question à propos de "Tri Linq dynamique fortement typé". Personnellement, je préfère la méthode de Ch00k, car il y a une vérification à la compilation impliquée et il y a très peu de code supplémentaire impliqué.

+0

et sa réponse (Ch00k) sera refactoring ainsi, faire un changement de nom d'une propriété, et les mises à jour de code, avec le nom de la propriété dans une chaîne, ça n'arrivera pas! –

4

Si vous avez déjà décidé qu'il doit s'agir d'une chaîne, vos options sont limitées. La bibliothèque Dynamic LINQ ferait en effet le travail, ou si vous voulez savoir comment tout cela fonctionne, regardez ce previous answer qui construit un Expression à partir de la chaîne à l'exécution. À l'heure actuelle, le code n'accepte qu'un seul membre et possède des méthodes séparées pour l'ascendance/la descente, mais à partir de cet exemple, il devrait être assez simple de passer une chaîne plus complexe et de la diviser; essentiellement:

IQueryable<T> query = ... 
string[] portions = orderBy.Split(' '); // split on space, arbitrarily 
if(portions.Length == 0) throw new ArgumentException(); 
IOrderedQueryable<T> orderedQuery = query.OrderBy(portions[0]); 
for(int i = 1 ; i < portions.Length ; i++) { // note we already did the zeroth 
    orderedQuery = orderedQuery.ThenBy(portions[i]); 
} 
return orderedQuery; 
+0

Il ne doit pas nécessairement s'agir d'une chaîne, mais comment passer la colonne de tri du contrôleur au référentiel/service? – Martin

+0

Si ce n'est pas une chaîne, alors le seul autre choix sensé serait une expression lambda, ou un objet qui encapsule plus d'une expression lambda. Ou utilisez simplement le OrderBy/ThenBy existant. –