comment utiliser un délégué pour obtenir le nom d'un CompiledQuery
-
01-10-2019 - |
Question
Je suis en train de trouver et exécuter un CompiledQuery donné le nom. Comment puis-je accéder à la requête compilé par nom et comment puis-je puis invoquer le délégué?
Voici autant que je peux obtenir - je reçois l'erreur "Erreur de liaison à la méthode cible
public class ActivityRepository
{
private readonly ActivityDataContext _db;
public ActivityRepository()
{
_db = new ActivityDataContext();
}
public static Func<ActivityDataContext, int, IQueryable<ProjectObject>>
GetCompiledLatestProjects = CompiledQuery.Compile
((ActivityDataContext db, int projectId) =>
from c in db.projectObjects
where c.projectId == projectId
select c);
public static Func<ActivityDataContext, Guid, IQueryable<Report>>
GetCompiledReports = CompiledQuery.Compile
((ActivityDataContext db, Guid itemId) =>
from c in db.Reports
where c.reportObjectId == itemId
select c);
// Autres requêtes compilées omises, mais les résultats sont des objets IQueryable qui mettent en œuvre une interface commune IProjectObject
delegate IQueryable<IProjectObject> MyDelegate();
static MyDelegate GetByName(object target, string methodName)
{
return (MyDelegate)Delegate.CreateDelegate
(typeof(MyDelegate), target, methodName);
}
public IList<Results> GetResults(string reportName)
{
IQueryable<ProjectObject> projectItems = GetLatestProjectObjects(projectId, quantity);
foreach (projectObject o in projectItems)
{
MyDelegate del = GetByName(this, reportName);
var dbReport = (IProjectObject) GetCompiledReports(_db, o.itemId).FirstOrDefault();
// add results to List and return
}
}
}
La solution
Vous pouvez probablement faire un peu de chemin poussif d'essayer d'identifier les champs de type Func <...> avec un DataContext comme premier argument que le retour IQueryable, mais vous trouverez peut-être beaucoup plus facile à simplement ajouter un attribut personnalisé :
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class DynamicQueryAttribute : Attribute { }
... que vous pouvez ensuite ajouter à votre champ:
[DynamicQuery]
public static Func<ActivityDataContext, int, IQueryable<ProjectObject>>
GetCompiledLatestProjects = CompiledQuery.Compile
((ActivityDataContext db, int projectId) =>
from c in db.projectObjects
where c.projectId == projectId
select c);
Vous pouvez ensuite sélectionner la requête sur cette base, et son nom:
public static IQueryable<IProjectObject> ExecuteQuery(Type ownerType, string name, params object[] args)
{
var query = typeof(ownerType)
.GetFields(BindingFlags.Public | BindingFlags.Static)
.Where(f =>
(f.GetCustomAttributes(typeof(DynamicQueryAttribute), false).Length > 0)
&& (f.Name.ToLowerInvariant() == name.ToLowerInvariant()))
.Select(f => (Delegate) f.GetValue(null))
.SingleOrDefault();
if (query == null)
return null;
return (IQueryable<IReportObject>)query.DynamicInvoke(args);
}
Utilisation:
var results = ExecuteQuery(
typeof(ActivityRepository),
"GetCompiledLatestProjects",
dataContext,
projectId);
Hope qui aide:)