public override CompoundUpdateCommand Visit(CompoundUpdateCommand c) { foreach (Command cc in c.InnerCommands) Visit(cc); return c; }
public void Process(CompoundUpdateCommand c) { foreach(Command cc in c.InnerCommands) cc.Accept(this); }
public void Process(CompoundUpdateCommand c) { // As a CompoundUpdateCommand can also contain CreateAttributeCommand we convert them if necessary for (int i = 0; i < c.InnerCommands.Count; i++) if (c.InnerCommands[i] is CreateAttributeCommand) { CreateAttributeCommand uac = c.InnerCommands[i] as CreateAttributeCommand; c.InnerCommands[i] = new UpdateAttributeCommand(uac.ParentId, uac.ParentType, uac.Name, uac.Type, uac.Value); } ArrayList queries = new ArrayList(); CacheEntityEntry entityEntry = _Engine.GetCacheEntityEntry(c.ParentType); EntityMapping e = (EntityMapping)entityEntry.Mapping; Hashtable table = ProcessUpdateAttributeCommands(e, c.InnerCommands); foreach (CacheQueryEntry entry in InitializeCompoundUpdateCommand(e, c.InnerCommands).Values) { ArrayList genericEntries = new ArrayList(); if (entry.IsAttributeGenericQuery) { AttributeMapping a = e.Attributes["*"]; for (int index = 0; index < ((ArrayList)table[a]).Count; index++) { genericEntries.Add(entry.Clone()); } } foreach (Parameter p in entry.Parameters) { switch (p.Name) { // Process parameter value to "Entity Id" case "EntityId": { DictionaryEntry dEntry = FindDictionaryEntry(entry, queries); if (!queries.Contains(dEntry)) queries.Add(dEntry); if (!((IDbCommand)dEntry.Value).Parameters.Contains("@EntityId")) { IDbDataParameter param = _Driver.CreateParameter("EntityId", _Dialect.GetDbTypeToPrimaryKey(e.Ids[0].Generator), c.ParentId); ((IDbCommand)dEntry.Value).Parameters.Add(param); } } break; // Process parameter value to "Entity Discriminator" case "EntityDiscriminator": { DictionaryEntry dEntry = FindDictionaryEntry(entry, queries); if (!queries.Contains(dEntry)) queries.Add(dEntry); if (!((IDbCommand)dEntry.Value).Parameters.Contains("@EntityDiscriminator")) { IDbDataParameter param = _Driver.CreateParameter("EntityDiscriminator", DbType.String, c.ParentType); ((IDbCommand)dEntry.Value).Parameters.Add(param); } } break; // Process parameter value to "FK_Entity" case "FK_Entity": { AttributeMapping a = (AttributeMapping)p.TagMapping; if (!entry.IsAttributeGenericQuery && ((ArrayList)table[a]).Count == 0) { DictionaryEntry dEntry = FindDictionaryEntry(entry, queries); if (!queries.Contains(dEntry)) queries.Add(dEntry); IDbDataParameter param = _Driver.CreateParameter("FK_Entity", _Dialect.GetDbTypeToPrimaryKey(e.Ids[0].Generator), c.ParentId); ((IDbCommand)dEntry.Value).Parameters.Add(param); } foreach (UpdateAttributeCommand cc in (ArrayList)table[a]) { DictionaryEntry dEntry; if (entry.IsAttributeGenericQuery) dEntry = FindDictionaryEntry((CacheQueryEntry)genericEntries[((ArrayList)table[a]).IndexOf(cc)], queries); else dEntry = FindDictionaryEntry(entry, queries); if (!queries.Contains(dEntry)) queries.Add(dEntry); IDbDataParameter param = _Driver.CreateParameter("FK_Entity", DbType.String, c.ParentId); ((IDbCommand)dEntry.Value).Parameters.Add(param); } } break; // Process parameter value to "AttributeDiscriminator" case "AttributeDiscriminator": { AttributeMapping a = (AttributeMapping)p.TagMapping; if (!entry.IsAttributeGenericQuery && ((ArrayList)table[a]).Count == 0) { DictionaryEntry dEntry = FindDictionaryEntry(entry, queries); if (!queries.Contains(dEntry)) queries.Add(dEntry); IDbDataParameter param = _Driver.CreateParameter("AttributeDiscriminator", DbType.String, a.Name); ((IDbCommand)dEntry.Value).Parameters.Add(param); } foreach (UpdateAttributeCommand cc in (ArrayList)table[a]) { DictionaryEntry dEntry; if (entry.IsAttributeGenericQuery) dEntry = FindDictionaryEntry((CacheQueryEntry)genericEntries[((ArrayList)table[a]).IndexOf(cc)], queries); else dEntry = FindDictionaryEntry(entry, queries); if (!queries.Contains(dEntry)) queries.Add(dEntry); IDbDataParameter param = _Driver.CreateParameter("AttributeDiscriminator", DbType.String, cc.Name); ((IDbCommand)dEntry.Value).Parameters.Add(param); } } break; // Process value to attribute default: { if (p.TagMapping as AttributeMapping != null) { AttributeMapping a = (AttributeMapping)p.TagMapping; if (!entry.IsAttributeGenericQuery && ((ArrayList)table[a]).Count == 0) { DictionaryEntry dEntry = FindDictionaryEntry(entry, queries); if (!queries.Contains(dEntry)) queries.Add(dEntry); // if attributecommand not find : apply a default value // initialize value to parameter SerializableType serializableType = a.GetSerializableType(a.DbType, a.Type); object value = null; if (a.DefaultValue != null) { switch (serializableType) { case SerializableType.BinarySerialization: value = Utils.SerializeToArray(a.DefaultValue); break; case SerializableType.StringSerialization: value = Utils.SerializeToString(a.DefaultValue); break; case SerializableType.Standard: if (a.DefaultValue != String.Empty) value = a.DefaultValue; break; case SerializableType.String: value = Utils.ConvertToString(a.DefaultValue, a.Type); break; case SerializableType.Int: value = Convert.ToInt32(a.DefaultValue); break; } } object formattedValue = _Dialect.PreProcessValue(value); IDbDataParameter param = _Driver.CreateParameter(p.Name, a.DbType, formattedValue); ((IDbCommand)dEntry.Value).Parameters.Add(param); } foreach (UpdateAttributeCommand cc in (ArrayList)table[a]) { DictionaryEntry dEntry; if (entry.IsAttributeGenericQuery) dEntry = FindDictionaryEntry((CacheQueryEntry)genericEntries[((ArrayList)table[a]).IndexOf(cc)], queries); else dEntry = FindDictionaryEntry(entry, queries); if (!queries.Contains(dEntry)) queries.Add(dEntry); // if attributecommand not find : apply a default value object commandValue = cc == null ? a.DefaultValue : cc.Value; // initialize value to parameter SerializableType serializableType = a.Type == null ? a.GetSerializableType(a.DbType, cc.Type) : a.GetSerializableType(a.DbType, a.Type); object value = null; if (commandValue != null) { switch (serializableType) { case SerializableType.BinarySerialization: value = Utils.SerializeToArray(commandValue); break; case SerializableType.StringSerialization: value = Utils.SerializeToString(commandValue); break; case SerializableType.Standard: value = commandValue; break; case SerializableType.String: //value = Utils.ConvertToString(commandValue, cc.Type, true); value = Utils.ConvertToString(commandValue, cc.Type); break; case SerializableType.Int: value = Convert.ToInt32(commandValue); break; } } object formattedValue = _Dialect.PreProcessValue(value); IDbDataParameter param = a.CreateDbDataParameter(p.Name, formattedValue); ((IDbCommand)dEntry.Value).Parameters.Add(param); } } else if (p.TagMapping as PrimaryKeyMapping != null) { string[] parentIds = c.ParentId.Split(SqlMapperProvider.IDSEP); int idPosition = int.Parse(p.Name.Replace("Id", string.Empty)); DictionaryEntry dEntry = FindDictionaryEntry(entry, queries); if (!queries.Contains(dEntry)) queries.Add(dEntry); ((IDbCommand)dEntry.Value).Parameters.Add(_Driver.CreateParameter(p.Name, _Dialect.GetDbTypeToPrimaryKey(e.Ids[idPosition].Generator), ConvertId(e.Ids[idPosition].Generator, parentIds[idPosition]))); } } break; } } } foreach (DictionaryEntry dEntry in queries) { IDbCommand command = (IDbCommand)dEntry.Value; // By using OleDb, the order of IDataParameter must match // the order of the values in the request _Driver.PreProcessQuery(command); command.Transaction = _Transaction; if (_Engine.TraceSqlSwitch.Enabled) { TraceHelpler.Trace(command, _Dialect); } command.ExecuteNonQuery(); } }
public abstract CompoundUpdateCommand Visit(CompoundUpdateCommand item);
/// <summary> /// Creates Compound commands if necessary /// </summary> /// <param name="commands"></param> private Command[] OptimizeCommands(SyncEngine engine, IList<Entity> commands) { if (commands == null) throw new ArgumentNullException("commands"); if (commands.Count == 0) return new Command[0]; HashedList<Command> optimizedCommands = new HashedList<Command>(); System.Collections.Generic.List<CompoundCreateCommand> createdCommands = new System.Collections.Generic.List<CompoundCreateCommand>(); int j; for (int i = 0; i < commands.Count; i++) { Entity e = commands[i]; string currentId = e.GetString(SyncUtils.PARENTID); int transaction = e.GetInt32(SyncUtils.TRANSACTION); switch (e.Type) { case SyncUtils.CREATE_ENTITY: string createType = e.GetString(SyncUtils.TYPE); j = i + 1; CompoundCreateCommand ccc = new CompoundCreateCommand(currentId, createType, new List<AttributeCommand>()); CompoundCreateCommand actual = createdCommands.Find(delegate(CompoundCreateCommand toFind) { return toFind.ClientId == ccc.ClientId && toFind.ParentId == ccc.ParentId && toFind.Type == ccc.Type; }); if (actual == null) { createdCommands.Add(ccc); optimizedCommands.Add(ccc); while (j < commands.Count) { string subType = commands[j].GetString(SyncUtils.PARENTTYPE); string subId = commands[j].GetString(SyncUtils.PARENTID); int subTransaction = commands[j].GetInt32(SyncUtils.TRANSACTION); string subCommand = commands[j].Type; if (commands[j].Type == SyncUtils.CREATE_ATTRIBUTE && subId == currentId && subType == createType) { if (subTransaction != transaction) break; ccc.InnerCommands.Add((AttributeCommand)engine.CreateCommand(commands[j])); commands.RemoveAt(j); } else { j++; } } } else { optimizedCommands.Remove(actual); optimizedCommands.Add(ccc); createdCommands.Remove(actual); createdCommands.Add(ccc); } break; case SyncUtils.UPDATE_ATTRIBUTE: string updateType = e.GetString(SyncUtils.PARENTTYPE); j = i + 1; CompoundUpdateCommand cuc = new CompoundUpdateCommand(currentId, updateType, new List<AttributeCommand>()); cuc.InnerCommands.Add((AttributeCommand)engine.CreateCommand(commands[i])); optimizedCommands.Add(cuc); while (j < commands.Count) { string subType = commands[j].GetString(SyncUtils.PARENTTYPE); string subId = commands[j].GetString(SyncUtils.PARENTID); int subTransaction = commands[j].GetInt32(SyncUtils.TRANSACTION); string subCommand = commands[j].Type; if (commands[j].Type == SyncUtils.UPDATE_ATTRIBUTE && subId == currentId && subType == updateType) { if (subTransaction != transaction) break; cuc.InnerCommands.Add((AttributeCommand)engine.CreateCommand(commands[j])); commands.RemoveAt(j); } else { j++; } } break; default: optimizedCommands.Add(engine.CreateCommand(e)); break; } } Command[] result = new Command[optimizedCommands.Count]; for (int i = 0; i < result.Length; i++) result[i] = (Command)optimizedCommands[i]; return result; }
public override CompoundUpdateCommand Visit(CompoundUpdateCommand item) { Mapping.Entity entity = engine.Provider.Mapping.Entities[item.ParentEntity.Type]; UpdateStatement update = engine.Provider.Mapping.Mapper.Update(entity); commands.Add(item.ParentEntity, update); foreach (Command command in item.InnerCommands) Visit(command); return item; }
/// <summary> /// Generated a set of commands to be processed to take into account any modification applied to an entity graph /// </summary> /// <param name="entity">The Entity to compute</param> /// <param name="processing">A collection of all currently processed entities</param> /// <param name="commands">A collection of all currently created commands</param> public void ComputeChanges(Entity entity, ICollection<Entity> processing, ICollection<Command> commands) { // Nothing to do if the entity is currently processed if (processing.Contains(entity)) return; processing.Add(entity); // To know if we can optimize the command with a compound bool canCreateCompound = true; // Will contain the commands created for the attributes of the current entity List<AttributeCommand> attributeCommands = new List<AttributeCommand>(entity.Count); // First process all attributes not to increase the stack size because of deep hierarchies in the object graph and the recursive algorithm if (entity.State == State.Modified || entity.State == State.New) foreach (Entry e in entity) { if (!e.IsEntity) { // The current entry is an Attribute switch (e.State) { case State.Deleted: attributeCommands.Add(new DeleteAttributeCommand(e)); break; case State.Modified: attributeCommands.Add(new UpdateAttributeCommand(e)); break; case State.New: attributeCommands.Add(new CreateAttributeCommand(e)); break; default: break; } } } // Selects the optimized command /// TODO: Add a property to PE so that the user could specify whether he wants all attributes to be sent with a compound command switch (entity.State) { case State.New: if (canCreateCompound) commands.Add(new CompoundCreateCommand(entity, attributeCommands)); else { commands.Add(new CreateEntityCommand(entity)); foreach (Command attributeCommand in attributeCommands) commands.Add(attributeCommand); } break; case State.Deleted: commands.Add(new DeleteEntityCommand(entity.Id, entity.Type)); break; case State.Modified: if (attributeCommands.Count > 1) { CompoundUpdateCommand cuc = new CompoundUpdateCommand(entity, attributeCommands); commands.Add(cuc); } else foreach (Command attributeCommand in attributeCommands) commands.Add(attributeCommand); break; default: foreach (Command attributeCommand in attributeCommands) commands.Add(attributeCommand); break; } foreach (Entry e in entity) { if (e.IsEntity) { Model.Reference referenceModel = Model.GetReference(entity.Type, e.Name); if (e.IsMultiple) { foreach (Entity child in ((IEnumerable<Entity>)e)) { ComputeChanges(child, processing, commands); switch (e.State) { case State.New: CreateReferenceCommand crc1 = new CreateReferenceCommand(referenceModel, entity, child); commands.Add(crc1); break; case State.Deleted: DeleteReferenceCommand drc = new DeleteReferenceCommand(referenceModel, entity, child); commands.Add(drc); break; } } } else { // The current entry is an Entity Entity child = (Entity)e.Value; ComputeChanges(child, processing, commands); switch (e.State) { case State.New: CreateReferenceCommand crc1 = new CreateReferenceCommand(referenceModel, entity, child); commands.Add(crc1); break; case State.Deleted: DeleteReferenceCommand drc = new DeleteReferenceCommand(referenceModel, entity, child); commands.Add(drc); break; } } } } }