I using the following library to do the Bulk insert. enter link description here i am trying to bulk insert a huge amount of data with its related items the solution is working fine with the first level but not inserting the children.
So, I have the following generic class
public class EFBatchOperation<TContext, T> : IEFBatchOperationBase<TContext, T>, IEFBatchOperationFiltered<TContext, T>
where T : class
where TContext : DbContext{
private ObjectContext context;
private DbContext dbContext;
private IDbSet<T> set;
private Expression<Func<T, bool>> predicate;
public EFBatchOperation(TContext context, IDbSet<T> set)
{
this.dbContext = context;
this.context = (context as IObjectContextAdapter).ObjectContext;
this.set = set;
}
public static IEFBatchOperationBase<TContext, T> For<TContext, T>(TContext context, IDbSet<T> set)
where TContext : DbContext
where T : class
{
return new EFBatchOperation<TContext, T>(context, set);
}
public BatchOperationResult InsertAll<TEntity>(IEnumerable<TEntity> items, DbConnection connection = null, int? batchSize = null) where TEntity : class, T
{
// the problem is here I want to call the current function 'InsertAll' but after changing the type of the function. passing a different type to the function. I tried the following but its not working var connectionToUse = connection ?? con.StoreConnection;
var currentType = typeof(TEntity);
var provider = Configuration.Providers.FirstOrDefault(p => p.CanHandle(connectionToUse));
if (provider != null && provider.CanInsert)
{
var mapping = EntityFramework.Utilities.EfMappingFactory.GetMappingsForContext(this.dbContext);
// use of T to get Type Mapping
var typeMapping = mapping.TypeMappings[typeof(T)];
var tableMapping = typeMapping.TableMappings.First();
var properties = tableMapping.PropertyMappings
.Where(p => currentType.IsSubclassOf(p.ForEntityType) || p.ForEntityType == currentType)
.Select(p => new ColumnMapping { NameInDatabase = p.ColumnName, NameOnObject = p.PropertyName }).ToList();
if (tableMapping.TPHConfiguration != null)
{
properties.Add(new ColumnMapping
{
NameInDatabase = tableMapping.TPHConfiguration.ColumnName,
StaticValue = tableMapping.TPHConfiguration.Mappings[typeof(TEntity)]
});
}
provider.InsertItems(items, tableMapping.Schema, tableMapping.TableName, properties, connectionToUse, batchSize);
var objectContext = ((IObjectContextAdapter)this.dbContext).ObjectContext;
var os = objectContext.CreateObjectSet<TEntity>();
var foreignKeyProperties = os.EntitySet.ElementType.NavigationProperties.Where(x => x.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
Type entityType = typeof(TEntity);
foreach (var foreignKeyProperty in foreignKeyProperties)
{
var childProperty = foreignKeyProperty.ToEndMember.GetEntityType();
foreach (var item in items)
{
var childValue = entityType.GetProperty(foreignKeyProperty.Name).GetValue(item);
Type childValueType = childProperty.GetType();
//MethodInfo method = typeof(EFBatchOperation).GetMethod("InsertAll");
MethodInfo method = typeof(EFBatchOperation<TContext, T>).GetMethod("InsertAll");
var newMethod = method.MakeGenericMethod(new[] { childValueType.DeclaringType });
newMethod.Invoke(this, new object[] { childValue });
// InsertAll<>(childValue, connection, batchSize);
}
}
}
}
I am calling InsertAll function as follows:
BatchOperationResult batchOperationResult = EFBatchOperation.For(context, dbSet).InsertAll(collectionOfEntitiesToInsert);
the problem is here I want to call the current function 'InsertAll' but after changing the type of the function. passing a different type to the function.
I have tried to call the function using reflection but its not working using the following code
MethodInfo method = typeof(EFBatchOperation<TContext, T>).GetMethod("InsertAll");
var newMethod = method.MakeGenericMethod(new[] { childValueType });
newMethod.Invoke(this, new object[] { childValue });
and I got the following error
GenericArguments [0], "System.Data.Entity.Core.Metadata.Edm.EntityType" for "EntityFramework.Utilities.BatchOperationResult InsertAll [TEntity] (System.Collections.Generic.IEnumerable
1 [TEntity], System.Data.Common .DbConnection, System.Nullable
1 [System.Int32]) "exceeds the" TEntity "type constraint.
Update:
I'm assuming that type T
is some base class that all of your model entities extend? Including this childValueType
?
From the error message, System.Data.Entity.Core.Metadata.Edm.EntityType
does not qualify for the constraints on TEntity
.
EntityType
is the EF Core implementation of IEntityType
. Though you have not included in your example where childValueType
is defined, I believe you have assigned childValueType = [IEntityType].GetType()
, where you intended childValueType = [IEntityType].ClrType
.
Update, now that you have added more code. As I guessed, this; childProperty.GetType();
should be childProperty.ClrType
.