public static void TestFieldExtract() { var extractor = new FieldExtract <C, int>(fields); var results = extractor.Extract(c1); //var dresults = extractor.ExtractAsDict(c1); try { var fails = new FieldExtract <C, string>(fields); } catch (InvalidOperationException) { } ; var ee = new FieldExtract <C, DateTime?>(new[] { "mynullable" }); var r = ee.Extract(c1); //var e2 = new FieldExtract<C, object>(fields); //e2.Extract(c1); var e3 = new FieldExtract <C, DateTime>(new[] { "date" }); var r3 = e3.Extract(c1); }
public static void TestExtractToArrays() { var extractor = new FieldExtract <C, object>(new[] { "a", "b", "s" }); var results = extractor.Extract(c1); var extracted = FieldExtractUtil.ExtractToObjectArrays(extractor, new[] { c1, c2, c1, c2 }); var serialized = JsonConvert.SerializeObject(extracted); Assert.AreEqual(serialized, @"[[100,100,100,100],[12,12,12,12],[""one"",""two"",""one"",""two""]]"); }
public static void Benchmark() { var c1 = new C() { a = 666, b = 12, date = DateTime.Now, mynullable = DateTime.Now }; var d1 = new D() { a = 666, b = 8, c = 9, date = DateTime.Now, mynullable = DateTime.Now }; var fields = new[] { "a", "b" }; WriteLine("Stats (microseconds) per iteration"); RepeatBench("new Differ()", 1000, () => { var dd = new Differ <C, D>(fields); }); var d = new Differ <C, D>(fields); RepeatBench("Compare small objects", 1000000, () => { var res = d.Compare(c1, d1); }); RepeatBench("new FieldExtract()", 1000, () => { var dd = new FieldExtract <C, int>(fields); }); var extractor = new FieldExtract <C, int>(fields); RepeatBench("Extract integers", 1000000, () => { var ints = extractor.Extract(c1); }); // big data var big1 = new BigDto(); var big2 = new BigDto(); var bigprops = ReflectionHelper.CollectProps <BigDto>(); var bigpropnames = bigprops.SelectMany(p => p.Item2).ToArray(); RepeatBench("new Differ() for big class", 100, () => { var dd = new Differ <BigDto, BigDto>(bigpropnames); }); var bigd = new Differ <BigDto, BigDto>(bigpropnames); RepeatBench("Compare large objects", 10000, () => { bigd.Compare(big1, big2); }); var types = ReflectionHelper.CollectProps <BigDto>(); var e4 = ReflectionHelper.GetExtractorFor <BigDto, int>(types); var e5 = ReflectionHelper.GetExtractorFor <BigDto, string>(types); var e6 = ReflectionHelper.GetExtractorFor <BigDto, decimal>(types); RepeatBench("Extract fields from large object", 10000, () => { var r1 = e4.Extract(big1); var r2 = e5.Extract(big1); var r3 = e6.Extract(big1); }); RepeatBench("Extract fields from large object, convert to dict, naive", 10000, () => { var pd = e4.ResultsAsDict(e4.Extract(big1).Select(i => i.ToString()).ToList()) .Union(e5.ResultsAsDict(e5.Extract(big1).Select(e => e.ToString()).ToList())) .Union(e6.ResultsAsDict(e6.Extract(big1).Select(e => e.ToString()).ToList())); }); var boxedExtract = new FieldExtract <BigDto, object>(bigpropnames); RepeatBench("Extract fields, boxed", 100000, () => { var r1 = boxedExtract.Extract(big1); }); RepeatBench("Extract fields from large dto. string -> object dict", 10000, () => { var r1 = boxedExtract.Extract(big1); var r2 = boxedExtract.ResultsAsZip(r1); }); var propertyInfos = typeof(BigDto).GetProperties(); RepeatBench("Extract fields with reflection", 10000, () => { foreach (var p in propertyInfos) { var val = p.GetValue(big1); } }); RepeatBench("Extract fields with reflection, convert to string dict", 10000, () => { var resdict = new Dictionary <string, string>(); foreach (var p in propertyInfos) { var val = p.GetValue(big1); var s = val.ToString(); resdict[p.Name] = s; } }); var copier = new FieldCopier <BigDto, BigDto>(bigpropnames); RepeatBench("Copy big object", 100000, () => { copier.Copy(big1, big2); }); }
// you should use this to create inserters BUT you should cache them // if rules are used, column names are guessed // yeah use [Table] and [Column] instead public static FastBulkInserter <TEntity> CreateBulkInserter <TEntity>(TableMappingRules rules = null) { var guessingMode = rules != null; var props = ReflectionHelper.GetProps <TEntity>(); var tableAttrs = typeof(TEntity).GetCustomAttributes(typeof(TableAttribute), true); string tableName = null; if (rules != null) { tableName = rules.TableName; } else { tableName = tableAttrs.Length > 0 ? ((TableAttribute)tableAttrs[0]).Name : null; } var mappedProps = new List <MapperPropertyData>(); var sql = new StringBuilder(); sql.Append("INSERT INTO "); sql.Append(tableName); sql.Append(" ("); // yeah we build this at the same cycle var valuesSql = new StringBuilder(); valuesSql.Append("VALUES ("); int index = 0; var mappedColumnNames = new List <string>(props.Length); foreach (var prop in props) { var columnAttr = prop.GetCustomAttributes(typeof(ColumnAttribute), true); // we only take first column attribute var columnName = columnAttr.Length > 0 ? ((ColumnAttribute)columnAttr[0]).Name : null; if (columnName == null && !guessingMode) { // we skip columns with no [Column] attribute continue; } var typeOk = ParameterTypeMap.TryGetValue(prop.PropertyType, out var recommendedParamType); if (!typeOk && prop.PropertyType.IsEnum) { typeOk = true; recommendedParamType = DbParameterTypeNumbers.Number; } if (!typeOk) { // skip unknown parameters. TODO: log this? // example of skipped types: collections, navigation props etc continue; } if (guessingMode) { columnName = rules.ColumnNameGenerator(prop); // a way to skip property - return null from name generator if (columnName == null) { continue; } } var paramNameInQuery = ":B" + index.ToString(); mappedProps.Add(new MapperPropertyData { Name = prop.Name, DbColumnName = columnName, FieldType = prop.PropertyType, ParameterNameInQuery = paramNameInQuery, RecommendedDbType = recommendedParamType }); mappedColumnNames.Add(prop.Name); sql.Append(columnName); sql.Append(","); index++; valuesSql.Append(paramNameInQuery); valuesSql.Append(","); } ; // remove last ',' and close both strings sql.Length--; sql.Append(") "); valuesSql.Length--; valuesSql.Append(')'); sql.Append(valuesSql); var finalSql = sql.ToString(); var extractor = new FieldExtract <TEntity, object>(mappedColumnNames.ToArray()); var bulkInserter = new FastBulkInserter <TEntity>() { InsertSql = finalSql, Properties = mappedProps, TableName = tableName, FieldExtractor = extractor }; return(bulkInserter); }