J'utilise une version modifiée de LinqKit
afin d'avoir mes extensions en un seul endroit.Expression statique en tant que propriété d'instance pour les requêtes linq dynamiques
Par conséquent, j'ai une seule partie de chacune de mes classes d'entités où je définis mon expression, par ex. pour tblMain
:
public partial class tblMain
{
public static Expression<Func<tblMain, bool>> IsVisible => (e) => e.MainStatus == "Visible";
}
Dans une requête, je suis maintenant capable d'écrire quelque chose comme ça
var visibleEntries = dbContext
.tblMain
.AsExpandable()
.Where(m => tblMain.IsVisible.Invoke(m))
.ToList();
qui me retourner toutes les entrées visibles de la table tblMain
.
Je me demandais s'il y avait un moyen de ne pas avoir cette propriété statique. Cela me permettrait d'utiliser Interfaces
comme IVisibilityEntity
pour forcer une propriété publique IsVisible
sur des types spécifiques.
Pour l'instant j'ai fini avec:
public Expression<Func<bool>> IsVisible2 => Expression.Lambda<Func<bool>>(Expression.Invoke(IsVisible, Expression.Variable(typeof(tblMain))));
mais cela me jette une exception
InvalidOperationException: variable 'm' de type 'tblMain' référencé du champ d'application '', mais ce n'est pas défini.
Même chose lors de l'utilisation de Expression.Constant(this, typeof(tblMain))
comme deuxième paramètre.
Ce que j'aimerais avoir est une requête comme
var visibleEntries = dbContext
.tblMain
.AsExpandable()
.Where(m => m.IsVisible.Invoke())
.ToList();
Cela peut sembler pas beaucoup d'un changement. Mais je veux vraiment pouvoir utiliser la fonction d'interface pour décrire mon modèle de base de données sous-jacent.
Avec des interfaces, il permet également des vérifications, par ex. if(myEntity is IVisibilityEntity)
pour effectuer des tâches de visibilité spécifiques.
Des idées si cela est possible et comment cela peut-il être réalisé?
Édition 1
Dès le premier commentaire. J'utilise LinqKit
pour permettre la même logique pour les sous-requêtes:
var visibleEntries = dbContext
.tblMain
.AsExpandable()
.Where(m => tblMain.IsVisible.Invoke(m))
.Select(m => new
{
VisibleSubs = m.tblSub.Where(s => tblSub.IsVisible.Invoke(s)).Select(s => new
{
// ...
})
})
.ToList();
La requête serait au-dessus de me donner tous les principaux-entrées visibles et leurs associés (et visibles) sous-entrées. Mais ce n'est pas possible d'écrire simplement m.tblSub.Where(tblSub.IsVisible)
car cela montre
CS1929 'ICollection<tblSub>' does not contain a definition for 'Where' and the best extension method overload 'Queryable.Where<tblSub>(IQueryable<tblSub>, Expression<Func<tblSub, bool>>)' requires a receiver of type 'IQueryable<tblSub>'
Dans votre premier extrait, vous pouvez écrire '.Where (tblMain.IsVisible)' et vous n'avez même plus besoin de LINQKit. – Servy
@Servy Je connais cet usage.S'il vous plaît voir ma question mise à jour ('Edit 1'). De plus, cette solution ne résoudra pas le problème d'interface et ne convient pas aux sous-requêtes. – KingKerosin