public void InitBuilder( EntityInfo entityInfo, Func <Type, NpgsqlDataReader, string, object> readerFunc) { var name = NpgsqlBulkUploader.GetUniqueName(typeof(T).Name); assemblyName = new AssemblyName { Name = name }; assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly( assemblyName, AssemblyBuilderAccess.Run); moduleBuilder = assemblyBuilder.DefineDynamicModule(name); typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public); GenerateWriteCode(entityInfo, readerFunc); }
public static List <T> BulkSelect <T, TKey>( this IQueryable <T> source, Expression <Func <T, TKey> > keyExpression, IEnumerable <TKey> keyData) { EnsureNoNavigationProperties(keyExpression); BulkSelectInterceptor.StartInterception(); var keyDataTable = NpgsqlBulkUploader.GetUniqueName("_schema_"); var schemaQuery = source.Select(keyExpression); var schemaSql = $"CREATE TEMP TABLE {keyDataTable} ON COMMIT DROP AS ({schemaQuery} LIMIT 0)"; var context = NpgsqlHelper.GetContextFromQuery(source); var conn = NpgsqlHelper.GetNpgsqlConnection(context); var localTr = NpgsqlHelper.EnsureOrStartTransaction(context, IsolationLevel.ReadCommitted); try { context.Database.ExecuteSqlCommand(schemaSql); var columnsInfo = NpgsqlHelper.GetColumnsInfo(context, keyDataTable); var propsMap = GetPropertiesMap( ((IObjectContextAdapter)context).ObjectContext, schemaQuery.Expression, typeof(TKey)); var mapsInfo = new List <MappingInfo>(); foreach (var propMap in propsMap) { var cinfo = columnsInfo[propMap.Item2]; mapsInfo.Add(new MappingInfo() { Property = propMap.Item1, ColumnInfo = cinfo, NpgsqlType = NpgsqlBulkUploader.GetNpgsqlType(cinfo) }); } var columnsCsv = string.Join(", ", mapsInfo.Select(x => NpgsqlHelper.GetQualifiedName(x.ColumnInfo.ColumnName))); var copySql = $"COPY {keyDataTable} ({columnsCsv}) FROM STDIN (FORMAT BINARY)"; using (var importer = conn.BeginBinaryImport(copySql)) { foreach (var kd in keyData) { importer.StartRow(); foreach (var kp in mapsInfo) { importer.Write(kp.Property.GetValue(kd), kp.NpgsqlType); } } importer.Complete(); } var whereSql = string.Join(" AND ", mapsInfo.Select(x => { var sourceColumn = NpgsqlHelper.GetQualifiedName(x.ColumnInfo.ColumnName); var targetColumn = NpgsqlHelper.GetQualifiedName(x.ColumnInfo.ColumnName); var clause = $"source.{sourceColumn} = {keyDataTable}.{targetColumn}"; if (x.IsNullableInClr) { clause = $"({clause} OR (source.{sourceColumn} IS NULL AND {keyDataTable}.{targetColumn} IS NULL))"; } return(clause); })); var selectSql = $"SELECT source.* FROM ({source}) as source\n" + $"JOIN {keyDataTable} ON {whereSql}"; BulkSelectInterceptor.SetReplaceQuery(source.ToString(), selectSql); var result = source.ToList(); localTr?.Commit(); return(result); } catch { localTr?.Rollback(); throw; } finally { BulkSelectInterceptor.StopInterception(); } }