Es gibt keine wirklich einfache Möglichkeit, mit einem Fund zu filtern. Ich habe mir jedoch einen genauen Weg ausgedacht, um die Funktionalität zu replizieren. Beachten Sie jedoch einige Punkte für meine Lösung.
Mit dieser Lösung können Sie generisch filtern, ohne den Primärschlüssel in .net-core zu kennen
Die Suche unterscheidet sich grundlegend, da die Entität abgerufen wird, wenn sie in der Nachverfolgung vorhanden ist, bevor die Datenbank abgefragt wird.
Darüber hinaus kann es nach einem Objekt filtern, sodass der Benutzer den Primärschlüssel nicht kennen muss.
Diese Lösung ist für EntityFramework Core.
- Dies erfordert Zugriff auf den Kontext
Hier sind einige Erweiterungsmethoden, die Sie hinzufügen können, um nach Primärschlüssel zu filtern
public static IReadOnlyList<IProperty> GetPrimaryKeyProperties<T>(this DbContext dbContext)
{
return dbContext.Model.FindEntityType(typeof(T)).FindPrimaryKey().Properties;
}
//TODO Precompile expression so this doesn't happen everytime
public static Expression<Func<T, bool>> FilterByPrimaryKeyPredicate<T>(this DbContext dbContext, object[] id)
{
var keyProperties = dbContext.GetPrimaryKeyProperties<T>();
var parameter = Expression.Parameter(typeof(T), "e");
var body = keyProperties
// e => e.PK[i] == id[i]
.Select((p, i) => Expression.Equal(
Expression.Property(parameter, p.Name),
Expression.Convert(
Expression.PropertyOrField(Expression.Constant(new { id = id[i] }), "id"),
p.ClrType)))
.Aggregate(Expression.AndAlso);
return Expression.Lambda<Func<T, bool>>(body, parameter);
}
public static Expression<Func<T, object[]>> GetPrimaryKeyExpression<T>(this DbContext context)
{
var keyProperties = context.GetPrimaryKeyProperties<T>();
var parameter = Expression.Parameter(typeof(T), "e");
var keyPropertyAccessExpression = keyProperties.Select((p, i) => Expression.Convert(Expression.Property(parameter, p.Name), typeof(object))).ToArray();
var selectPrimaryKeyExpressionBody = Expression.NewArrayInit(typeof(object), keyPropertyAccessExpression);
return Expression.Lambda<Func<T, object[]>>(selectPrimaryKeyExpressionBody, parameter);
}
public static IQueryable<TEntity> FilterByPrimaryKey<TEntity>(this DbSet<TEntity> dbSet, DbContext context, object[] id)
where TEntity : class
{
return FilterByPrimaryKey(dbSet.AsQueryable(), context, id);
}
public static IQueryable<TEntity> FilterByPrimaryKey<TEntity>(this IQueryable<TEntity> queryable, DbContext context, object[] id)
where TEntity : class
{
return queryable.Where(context.FilterByPrimaryKeyPredicate<TEntity>(id));
}
Sobald Sie diese Erweiterungsmethoden haben, können Sie wie folgt filtern:
query.FilterByPrimaryKey(this._context, id);