// we always refill the object with the current values from the DB even if we find the object (via PK in our cache) // as the expensive operation (fetching from DB is already done) through the cache we just ensure object identity private T CreateObject(IDataReader reader) { // create a new one of T var poco = ObjectFactory.Create(Entity.PocoType); var cache = _ctx.Cache; var pkValue = reader[Entity.PkColumn.Name]; // we now get a new empty cacheEntry or it already was present var cacheEntry = cache.GetOrInsert(Entity, (long)pkValue, poco); foreach (var col in QueriedColumns) { if (col.IsDbColumn) { if (col.IsShadowAttribute) { // foreign key / ManyToOne (exists in db and in object, but is a key - can not be set directly and needs to be lazily loaded) cacheEntry.ShadowAttributes[col.Name] = reader[col.Name]; } else { var value = reader[col.Name]; // specially handle enums if (col.PropInfo.PropertyType.IsEnum) { value = Enum.Parse(col.PropInfo.PropertyType, value as string); } // fill the originalEntries with values for changeTracking later if (!cacheEntry.OriginalPoco.ContainsKey(col.Name)) { cacheEntry.OriginalPoco.Add(col.Name, value); } // fill the object from the cache with values col.PropInfo.GetSetMethod(true).Invoke(cacheEntry.Poco, new[] { value }); } } else { if (col.Relation is ManyToMany relation) { } } } // instantiate the inner lazy loader in the object LazyLoadInjector.InjectLazyLoader <T>(poco, _ctx, Entity); return((T)cacheEntry.Poco); }
public List <T> ExecuteInsert <T>(InsertStatement <T> statement) { using var connection = _connection.Invoke(); connection.Open(); using IDbTransaction transaction = connection.BeginTransaction(); using var command = connection.CreateCommand(); command.CommandText = statement.AsSqlString(); command.Transaction = transaction; PrepareStatement(statement, command); try { var reader = command.ExecuteReader(); var entity = statement._entityExecutedOn; var pkCol = entity.PkColumn; var pocos = statement._pocos; var cache = _ctx.Cache; var enumerator = pocos.GetEnumerator(); // now we set the pks the db returned on our pocos and add them to the cache while (reader.Read() && enumerator.MoveNext()) { var poco = enumerator.Current; var pk = reader[pkCol.Name]; pkCol.PropInfo.SetMethod.Invoke(poco, new[] { pk }); var cacheEntry = cache.GetOrInsert(entity, (long)pk, poco); // now we fill originalPoco foreach (var col in entity.CombinedColumns()) { if (col.IsDbColumn) { if (col.IsShadowAttribute) { // TODO: maybe no entry? cacheEntry.ShadowAttributes[col.Name] = null; } else { var value = col.PropInfo.GetMethod.Invoke(poco, new object[0]); // fill the originalEntries with values for changeTracking later if (!cacheEntry.OriginalPoco.ContainsKey(col.Name)) { cacheEntry.OriginalPoco.Add(col.Name, value); } } } } LazyLoadInjector.InjectLazyLoader <T>(poco, _ctx, statement._entityExecutedOn); } reader.Close(); transaction.Commit(); return(pocos); } catch (Exception ex) { Console.WriteLine("Commit Exception Type: {0}", ex.GetType()); Console.WriteLine(" Message: {0}", ex.Message); transaction.Rollback(); throw ex; } }