Méthode générique de référentiel GetById utilisant un chargement rapide

J’utilise Entity Framework et voudrais créer une méthode GetById générique dans la classe Repository avec un chargement rapide :

Voici ma méthode qui utilise le chargement paresseux:

public virtual TEntity GetById(object id) { return DbSet.Find(id); } 

Je sais que la méthode Find ne prend pas en charge le chargement rapide, mais comment il est possible de modifier cette méthode pour utiliser le chargement rapide, de sorte que j’utilise cette méthode comme suit (pour un exemple):

 _unitOfWork.MyRepository.GetById(includeProperties: "Users"); 

Une solution possible consiste à utiliser FirstOrDefault avec un prédicat sur le DbSet avec Include s. Il n’est pas difficile de créer manuellement un prédicat à l’aide de la méthode Expression.Equal , mais le principal défi consiste à obtenir le nom de la propriété de clé. Heureusement, nous pouvons utiliser certaines méthodes ObjectContext pour le faire. L’implémentation pourrait donc ressembler à ceci (en supposant que nous ayons access à l’instance concrète DbContext ):

 public virtual TEntity GetById(object id, params ssortingng[] includeProperties) { var propertyName = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)DbContext).ObjectContext .CreateObjectSet().EntitySet.ElementType.KeyMembers.Single().Name; var parameter = Expression.Parameter(typeof(TEntity), "e"); var predicate = Expression.Lambda>( Expression.Equal( Expression.PropertyOrField(parameter, propertyName), Expression.Constant(id)), parameter); var query = DbSet.AsQueryable(); if (includeProperties != null && includeProperties.Length > 0) query = includeProperties.Aggregate(query, System.Data.Entity.QueryableExtensions.Include); return query.FirstOrDefault(predicate); } 

Ceci est la mise à jour pour Entity Framework Core 2.0. Cette méthode utilise également les nouvelles propriétés de métadonnées avec EF pour obtenir automatiquement les propriétés de navigation de premier niveau.

 public virtual T Get(object id) { var propertyName = "AddressId"; //get all navigation properties defined for entity var navigationProps = _context.Model.FindEntityType(typeof(T)).GetNavigations(); //turn those navigation properties into a ssortingng array var includeProperties = navigationProps.Select(p => p.PropertyInfo.Name).ToArray(); //make parameter of type T var parameter = Expression.Parameter(typeof(T), "e"); //create the lambda expression var predicateLeft = Expression.PropertyOrField(parameter, propertyName); var predicateRight = Expression.Constant(id); var predicate = Expression.Lambda>(Expression.Equal(predicateLeft, predicateRight), parameter); //get queryable var query = _context.Set().AsQueryable(); //apply Include method to the query multiple times query = includeProperties.Aggregate(query, Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.Include); //return first item in query return query.FirstOrDefault(predicate); }