【发布时间】:2021-11-10 23:23:07
【问题描述】:
我使用以下库进行批量插入。 enter link description here 我正在尝试批量插入大量数据及其相关项,该解决方案在第一级工作正常,但不插入子项。
所以,我有以下泛型类
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);
}
}
}
}
我调用 InsertAll 函数如下:
BatchOperationResult batchOperationResult = EFBatchOperation.For(context, dbSet).InsertAll(collectionOfEntitiesToInsert);
问题出在我想调用当前函数“InsertAll”但在更改函数类型之后。将不同的类型传递给函数。
我尝试使用反射调用该函数,但使用以下代码无法正常工作
MethodInfo method = typeof(EFBatchOperation<TContext, T>).GetMethod("InsertAll");
var newMethod = method.MakeGenericMethod(new[] { childValueType });
newMethod.Invoke(this, new object[] { childValue });
我收到以下错误
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.Nullable1 [System.Int32 ])"超出了"TEntity"类型约束。
更新:
- 这里的想法是插入与子相关的属性,因为原始代码只是插入了主实体,而不是子元素。
- 还用更多代码更新了代码,以阐明我在这里要做什么
【问题讨论】:
-
阅读异常信息。您的
childValueType变为int?并且没有通过通用约束 -
System.Data.Entity.Core.Metadata.Edm.EntityType?所以你的childValueType是IEntityType,而不是Type?那我觉得你需要childValueType.ClrType。 -
@JeremyLakeman 我认为你是对的我试图从值转换类型但我不能
-
你到底想写什么?你能用
context.ChangeTracker.TrackGraph(...)替换整个东西吗? -
@MohamedSalah 您不能批量插入多个表 - 假设
bulk insert您实际上是指使用批量插入机制。您必须先加载父表,然后再加载任何相关表。实际上,在批量操作期间禁用索引和外键约束以加快处理速度是很常见的。批量插入到暂存表中,然后更新目标表甚至使用分区切换来用暂存数据替换实际数据也很常见
标签: c# generics reflections