Sto usando System.Linq.Dynamic.Core;
e il seguente metodo di estensione per accedere dinamicamente a un DbSet per nome e generare query da stringhe.
Questo è il metodo di estensione:
namespace Microsoft.EntityFrameworkCore
{
public static partial class CustomExtensions
{
public static IQueryable Query(this DbContext context, string entityName) =>
context.Query(context.Model.FindEntityType(entityName).ClrType);
public static IQueryable Query(this DbContext context, Type entityType) =>
(IQueryable)((IDbSetCache)context).GetOrAddSet(context.GetDependencies().SetSource, entityType);
}
}
Questo è il modo in cui accedo a DbSet:
IQueryable<T> dbSet = (IQueryable<T>)_db.Query(entityName);
Funziona bene, posso creare una query e quindi creare una lista ma nessuna delle entità nidificate viene caricata. Sembra che IQueryable
non abbia una definizione per Include()
. Riesco a vedere includere il metodo se accedo al contesto db direttamente in modo normale ma non utilizzando questo metodo dinamico.
Come posso includere entità nidificate usando il metodo dinamico?
Prima di tutto Si sta utilizzando GetOrAddSet
di IDbSetCache
public interface IDbSetCache
// // Riepilogo: // Questa API supporta l'infrastruttura Entity Framework Core e non è intesa per // essere utilizzata direttamente dal codice. Questa API può cambiare o essere rimossa in futuro
Include
è il metodo di IQueryable<TEntity>
nella classe EntityFrameworkQueryableExtensions
di Microsoft.EntityFrameworkCore
, non per IQueryable
. La tua funzione restituisce IQueryable
Ti consiglierei di creare un metodo di estensione come di seguito,
public static IQueryable<T> MyQuery<T>(this DbContext context)
where T : class
{
return context.Set<T>().AsQueryable();
}
E puoi consumare,
var result = _dbContext.MyQuery<Employee>().Include("Department");
Per Dynamic include,
/// <summary>
/// Query with dynamic Include
/// </summary>
/// <typeparam name="T">Entity</typeparam>
/// <param name="context">dbContext</param>
/// <param name="includeProperties">includeProperties with ; delimiters</param>
/// <returns>Constructed query with include properties</returns>
public static IQueryable<T> MyQueryWithDynamicInclude<T>(this DbContext context, string includeProperties)
where T : class
{
string[] includes = includeProperties.Split(';');
var query = context.Set<T>().AsQueryable();
foreach (string include in includes)
query = query.Include(include);
return query;
}
Ho un codice pezzo per questo problema. Uso l'albero delle espressioni.
Il mio modello di entità come di seguito:
public class PortfolioTechnology
{
public int PortfolioId { get; set; }
public Portfolio Portfolio { get; set; }
public int TechnologyId { get; set; }
public Technology Technology { get; set; }
}
Il mio codice principale come di seguito:
public SharpListResponse<PortfolioTechnology> GetAll(Expression<Func<PortfolioTechnology, bool>> predicate,
params Expression<Func<PortfolioTechnology,object>>[] includes)
{
var query = _dbContext.PortfolioTechnology.AsQueryable();
foreach (var include in includes)
{
var memberExpression = include.Body as MemberExpression;
if (memberExpression != null)
query = query.Include(memberExpression.Member.Name);
}
var result = query.Where(predicate).ToList();
return new SharpListResponse<PortfolioTechnology>(result);
}
E utilizzare questo metodo come di seguito:
var list= _unitOfWork.PortfolioTechnologyRepository.GetAll(x => x.PortfolioId == id,
y => y.Technology);
Se si desidera includere più entità, ad esempio includere entità Portfolio e Technology, il codice come di seguito:
var list= _unitOfWork.PortfolioTechnologyRepository.GetAll(x => x.PortfolioId == id,
y => y.Technology,
x => x.Portfolio);
Nota: SharpListResponse è la classe wrapper. Il codice funziona senza di esso
Maggiori dettagli per SharpListResponse: https://www.nuget.org/packages/SharpRequestResponseWrapper/