基于EF8批量更新的扩展

发布时间 2024-01-04 09:34:21作者: urmnur

public static class EFCoreExtensions
{
	public static int Update<TEntity>(this IQueryable<TEntity> query, TEntity entity)
	{
		if (query == null) { return 0; }
		if (entity == null) { return 0; }
		var methods = typeof(SetPropertyCalls<TEntity>).GetMethods().Where(x => x.Name.ToLower() == "SetProperty".ToLower());
		var setProperty = methods.FirstOrDefault();
		foreach (var method in methods)
		{
			var ps = method.GetParameters();
			if (ps.Length != 2)
			{
				continue;
			}
			if (ps[1].ParameterType.IsGenericType)
			{
				continue;
			}
			setProperty = method;
		}
		var entityExpression = Expression.Parameter(typeof(TEntity), "a");
		var setPropertyExpression = Expression.Parameter(typeof(SetPropertyCalls<TEntity>), "x");
		Expression call = setPropertyExpression;
		var setCount = 0;
		foreach (var p in typeof(TEntity).GetProperties())
		{
			var value = p.GetValue(entity);
			if (value == null)
			{
				continue;
			}
			if (value is DateTime && ((DateTime)value) == DateTime.MinValue)
			{
				continue;
			}
			setCount++;
			var propertyMethod = p.GetGetMethod();
			var propertyExpression = Expression.Lambda(Expression.Property(entityExpression, propertyMethod), new[] { entityExpression });
			call = Expression.Call(call,
			  setProperty.MakeGenericMethod(value.GetType()),
			  propertyExpression,
			  Expression.Constant(value));
		}
		if (setCount == 0) { return 0; }
		var lambda = Expression.Lambda<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>>(call, setPropertyExpression);
		return RelationalQueryableExtensions.ExecuteUpdate(query, lambda);
	}
}