Example #1
0
        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();
            }
        }