MikaelEliasson / EntityFramework.Utilities

Provides extensions for EntityFramework that doesn't exist out of the box like delete and update by query and bulk inserts
443 stars 176 forks source link

How to use Bulk Update for all columns? #106

Open KiranSaj opened 7 years ago

KiranSaj commented 7 years ago

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));
    }
CodyMorris commented 6 years ago

Curious about this too

RudeySH commented 6 years ago

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.

TaoGodNo1 commented 5 years ago

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();
        }
RudeySH commented 5 years ago

@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;
}