MikaelEliasson/EntityFramework.Utilities

How to use Bulk Update for all columns?

Opened this issue · 4 comments

I have created following method to BulkUpdate. I am passing list to it. How to update all the column.
I want to make it generic method.

public virtual void BulkUpdate(IEnumerable entities)
{
if (entities == null)
throw new ArgumentNullException(nameof(entities));

        EFBatchOperation.For(_Context, _Entities).UpdateAll(entities,x => x.ColumnsToUpdate(c => c));
    }

Curious about this too

You can solve this using reflection. I have done it before, you have to build the updateSpecification parameter manually using reflection. Keep in mind that when doing so, you have to ignore certain properties, such as primary keys, computed columns, navigation properties, NotMapped properties, etc.

You can solve this using reflection. I have done it before, you have to build the updateSpecification parameter manually using reflection. Keep in mind that when doing so, you have to ignore certain properties, such as primary keys, computed columns, navigation properties, NotMapped properties, etc.
I using reflection and expression tree to write this function:

EFBatchOperation.For(_Context, _Entities).UpdateAll(entities,x => x.ColumnsToUpdate(CreateExpressionFromEntity<yourEntityType>()));





public static Expression<Func<TEntity, object>>[] CreateExpressionFromEntity<TEntity>()
        {
            var listExpr = new List<Expression<Func<TEntity, object>>>();
            foreach (var item in typeof(TEntity).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).Where(p => p.CanWrite))
            {
                var par = Expression.Parameter(typeof(TEntity));
                var pro = Expression.Property(par, item.Name);
                var conv = Expression.Convert(pro, typeof(object));
                listExpr.Add(Expression.Lambda<Func<TEntity, object>>(conv, par));
            }
            return listExpr.ToArray();
        }

@SuperGodTao that's a great start. I suggest adding the following:

// skip primary key properties
if (Attribute.IsDefined(item, typeof(KeyAttribute)))
{
	continue;
}

// skip generated properties
if (Attribute.IsDefined(item, typeof(DatabaseGeneratedAttribute)))
{
	continue;
}

// skip not mapped properties
if (Attribute.IsDefined(item, typeof(NotMappedAttribute)))
{
	continue;
}

// skip collection properties
if (item.PropertyType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
	continue;
}