EF核心元数据提供所有必要的信息。
您可以使用
Expression
类以动态生成这样的条件(伪代码):
(seedRows1.Key1 == e.Key1 && seedRows1.Key2 == e.Key2 ... && seeedRows1.KeyM == e.KeyM)
||
(seedRows2.Key1 == e.Key1 && seedRows2.Key2 == e.Key2 ... && seeedRows2.KeyM == e.KeyM)
...
||
(seedRowsN.Key1 == e.Key1 && seedRowsN.Key2 == e.Key2 ... && seeedRowsN.KeyM == e.KeyM);
从数据库返回匹配项。为了得到不匹配的项,可以简单地反转条件,并将其用作删除的谓词。请注意,对于单个pk,这将转换为
NOT IN (...)
SQL标准。
付诸行动:
private static void Delete<TEntity>(DbContext dbContext, IEnumerable<TEntity> seedRows)
where TEntity : class//, IBaseEntity
{
var entityType = dbContext.Model.FindEntityType(typeof(TEntity));
var entityPK = entityType.FindPrimaryKey();
var dbEntity = Expression.Parameter(entityType.ClrType, "e");
Expression matchAny = null;
foreach (var entity in seedRows)
{
var match = entityPK.Properties
.Select(p => Expression.Equal(
Expression.Property(dbEntity, p.PropertyInfo),
Expression.Property(Expression.Constant(entity), p.PropertyInfo)))
.Aggregate(Expression.AndAlso);
matchAny = matchAny != null ? Expression.OrElse(matchAny, match) : match;
}
var dbQuery = dbContext.Set<TEntity>().AsQueryable();
if (matchAny != null)
{
var predicate = Expression.Lambda<Func<TEntity, bool>>(Expression.Not(matchAny), dbEntity);
dbQuery = dbQuery.Where(predicate);
}
var dbEntities = dbQuery.ToList();
if (dbEntities.Count == 0) return;
dbContext.RemoveRange(dbEntities);
dbContext.SaveChanges();
}