Exemple #1
0
        static void TestViaInterfaceCase <T>(IEnumerable <T> data, DbContext context) where T : IHasId
        {
            var uploader = new NpgsqlBulkUploader(context);

            var properties = data
                             .First()
                             .GetType()
                             .GetProperties()
                             .ToArray();

            uploader.Insert(data, InsertConflictAction.UpdateProperty <T>(x => x.AddressId, properties));
        }
Exemple #2
0
        static async Task TestAsync(BulkContext context, NpgsqlBulkUploader uploader, List <Address> data)
        {
            Console.WriteLine("");
            Console.WriteLine("ASYNC version...");
            Console.WriteLine("");


            var sw = Stopwatch.StartNew();
            await uploader.InsertAsync(data);

            sw.Stop();
            Console.WriteLine($"Dynamic solution inserted {data.Count} records for {sw.Elapsed }");
            Trace.Assert(context.Addresses.Count() == data.Count);

            data.ForEach(x => x.HouseNumber += 1);

            sw = Stopwatch.StartNew();
            await uploader.UpdateAsync(data);

            sw.Stop();
            Console.WriteLine($"Dynamic solution updated {data.Count} records for {sw.Elapsed }");

            context.Database.ExecuteSqlCommand("TRUNCATE addresses CASCADE");
            sw = Stopwatch.StartNew();
            await uploader.ImportAsync(data);

            sw.Stop();
            Console.WriteLine($"Dynamic solution imported {data.Count} records for {sw.Elapsed }");

            // With transaction
            context.Database.ExecuteSqlCommand("TRUNCATE addresses CASCADE");

            using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            {
                await uploader.InsertAsync(data);
            }
            Trace.Assert(context.Addresses.Count() == 0);

            sw = Stopwatch.StartNew();
            await uploader.UpdateAsync(data);

            sw.Stop();
            Console.WriteLine($"Dynamic solution updated {data.Count} records for {sw.Elapsed } (after transaction scope)");

            // partial update 1
            sw = Stopwatch.StartNew();
            data.ForEach(x => x.StreetName = x.StreetName + " upd");
            await uploader.UpdateAsync(data, x => x.StreetName);

            sw.Stop();
            Console.WriteLine($"Dynamic solution updated {data.Count} records for {sw.Elapsed } (partial 1) Async");
        }
Exemple #3
0
        static void TestInheritanceCase()
        {
            var streets      = new[] { "First", "Second", "Third" };
            var codes        = new[] { "001001", "002002", "003003", "004004" };
            var extraNumbers = new int?[] { null, 1, 2, 3, 5, 8, 13, 21, 34 };

            var context = new BulkContext("DefaultConnection");

            context.Database.ExecuteSqlCommand("DELETE FROM addresses2");

            var data = Enumerable.Range(0, 100000)
                       .Select((x, i) => new Address2()
            {
                StreetName       = streets[i % streets.Length],
                HouseNumber      = i + 1,
                PostalCode       = codes[i % codes.Length],
                ExtraHouseNumber = extraNumbers[i % extraNumbers.Length],
                LocalizedName    = streets[i % streets.Length],
                Index1           = i,
                Index2           = i
            }).ToList();

            var uploader = new NpgsqlBulkUploader(context);

            context.Database.ExecuteSqlCommand("TRUNCATE addresses CASCADE");
            var sw = Stopwatch.StartNew();

            uploader.Insert(data);
            sw.Stop();
            Console.WriteLine($"Dynamic solution inserted {data.Count} records for {sw.Elapsed }");

            // checking consitency
            foreach (var addr in data)
            {
                if (addr.Index1 != addr.Index2)
                {
                    Console.WriteLine($"INCONSITENT! Id: {addr.AddressId}/{addr.Address2Id}, {addr.Index1} != {addr.Index2}");
                }
            }

            data.ForEach(x => x.HouseNumber += 1);

            sw = Stopwatch.StartNew();
            uploader.Update(data);
            sw.Stop();
            Console.WriteLine($"Dynamic solution updated {data.Count} records for {sw.Elapsed }");
        }
Exemple #4
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);
        }
Exemple #5
0
        static void TestPlainCase()
        {
            var streets      = new[] { "First", "Second", "Third" };
            var codes        = new[] { "001001", "002002", "003003", "004004" };
            var extraNumbers = new int?[] { null, 1, 2, 3, 5, 8, 13, 21, 34 };

            var context = new BulkContext("DefaultConnection");

            context.Database.ExecuteSqlCommand("TRUNCATE addresses cascade");

            var data = Enumerable.Range(0, 100000)
                       .Select((x, i) => new Address()
            {
                StreetName       = streets[i % streets.Length],
                HouseNumber      = i + 1,
                PostalCode       = codes[i % codes.Length],
                ExtraHouseNumber = extraNumbers[i % extraNumbers.Length]
            }).ToList();

            var uploader = new NpgsqlBulkUploader(context);

            context.Database.ExecuteSqlCommand("DELETE FROM addresses");
            var sw = Stopwatch.StartNew();

            HardcodedInsert(data, context);
            sw.Stop();
            Console.WriteLine($"Hardcoded solution inserted {data.Count} records for {sw.Elapsed }");

            context.Database.ExecuteSqlCommand("DELETE FROM addresses");
            sw = Stopwatch.StartNew();
            uploader.Insert(data);
            sw.Stop();
            Console.WriteLine($"Dynamic solution inserted {data.Count} records for {sw.Elapsed }");

            data.ForEach(x => x.HouseNumber += 1);

            sw = Stopwatch.StartNew();
            uploader.Update(data);
            sw.Stop();
            Console.WriteLine($"Dynamic solution updated {data.Count} records for {sw.Elapsed }");
        }
        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 = $"_schema_{DateTime.Now.Ticks}";
            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);

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

                var whereSql = string.Join(" AND ",
                                           mapsInfo.Select(x => $"source.{NpgsqlHelper.GetQualifiedName(x.ColumnInfo.ColumnName)}" +
                                                           $" = {keyDataTable}.{NpgsqlHelper.GetQualifiedName(x.ColumnInfo.ColumnName)}"));

                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();
            }
        }
Exemple #7
0
        static void TestPlainCase()
        {
            var streets      = new[] { "First", "Second", "Third" };
            var codes        = new[] { "001001", "002002", "003003", "004004" };
            var extraNumbers = new int?[] { null, 1, 2, 3, 5, 8, 13, 21, 34 };
            var addressTypes = new AddressType?[] { null, AddressType.Type1, AddressType.Type2 };
            var dates        = new DateTime?[] { null, DateTime.Now };
            var guids        = new Guid?[] { null, Guid.Empty };
            var decimals     = new decimal?[] { null, decimal.Zero };

            var context = new BulkContext("DefaultConnection");

            context.Database.ExecuteSqlCommand("TRUNCATE addresses cascade");

            var data = Enumerable.Range(0, 100000)
                       .Select((x, i) => new Address()
            {
                StreetName       = streets[i % streets.Length],
                HouseNumber      = i + 1,
                PostalCode       = codes[i % codes.Length],
                ExtraHouseNumber = extraNumbers[i % extraNumbers.Length],
                Type             = addressTypes[i % addressTypes.Length],
                Date             = dates[i % dates.Length],
                Guid             = guids[i % guids.Length],
                Dec = decimals[i % decimals.Length]
            }).ToList();

            var uploader = new NpgsqlBulkUploader(context);

            context.Database.ExecuteSqlCommand("DELETE FROM addresses");
            var sw = Stopwatch.StartNew();

            HardcodedInsert(data, context);
            sw.Stop();
            Console.WriteLine($"Hardcoded solution inserted {data.Count} records for {sw.Elapsed }");

            context.Database.ExecuteSqlCommand("DELETE FROM addresses");
            sw = Stopwatch.StartNew();

            uploader.Insert(data, InsertConflictAction.UpdateProperty <Address>(x => x.AddressId, x => x.Dec));

            uploader.Insert(data, InsertConflictAction.DoNothing());
            sw.Stop();
            Console.WriteLine($"Dynamic solution inserted {data.Count} records for {sw.Elapsed }");

            data.ForEach(x => x.HouseNumber += 1);

            sw = Stopwatch.StartNew();
            uploader.Update(data);
            sw.Stop();
            Console.WriteLine($"Dynamic solution updated {data.Count} records for {sw.Elapsed }");

            TestViaInterfaceCase(data, context);

            context.Database.ExecuteSqlCommand("TRUNCATE addresses CASCADE");
            sw = Stopwatch.StartNew();
            uploader.Import(data);
            sw.Stop();
            Console.WriteLine($"Dynamic solution imported {data.Count} records for {sw.Elapsed }");

            // With transaction
            context.Database.ExecuteSqlCommand("TRUNCATE addresses CASCADE");

            using (var transaction = new TransactionScope())
            {
                uploader.Insert(data);
            }
            Trace.Assert(context.Addresses.Count() == 0);

            sw = Stopwatch.StartNew();
            uploader.Update(data);
            sw.Stop();
            Console.WriteLine($"Dynamic solution updated {data.Count} records for {sw.Elapsed } (after transaction scope)");

            TestAsync(context, uploader, data).Wait();
        }