public override bool AddCommand(ModificationCommand modificationCommand) { Check.NotNull(modificationCommand, nameof(modificationCommand)); if (ModificationCommands.Count == 0) { ResetCommandText(); } if (!CanAddCommand(modificationCommand)) { return false; } _modificationCommands.Add(modificationCommand); _resultSetEnd.Add(true); if (!IsCommandTextValid()) { ResetCommandText(); _modificationCommands.RemoveAt(_modificationCommands.Count - 1); _resultSetEnd.RemoveAt(_resultSetEnd.Count - 1); return false; } return true; }
public override void AppendUpdateOperation( StringBuilder commandStringBuilder, ModificationCommand command) { Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); Check.NotNull(command, nameof(command)); var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToArray(); var conditionOperations = operations.Where(o => o.IsCondition).ToArray(); var readOperations = operations.Where(o => o.IsRead).ToArray(); AppendUpdateCommandHeader(commandStringBuilder, name, schema, writeOperations); if (readOperations.Length > 0) { AppendOutputClause(commandStringBuilder, readOperations); } AppendWhereClause(commandStringBuilder, conditionOperations); commandStringBuilder.Append(SqlGenerator.BatchCommandSeparator).AppendLine(); if (readOperations.Length == 0) { AppendSelectAffectedCountCommand(commandStringBuilder, name, schema); } }
public override void AppendInsertOperation( StringBuilder commandStringBuilder, ModificationCommand command) { Check.NotNull(command, nameof(command)); AppendBulkInsertOperation(commandStringBuilder, new[] { command }); }
public override ResultSetMapping AppendInsertOperation( StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) { Check.NotNull(command, nameof(command)); return AppendBulkInsertOperation(commandStringBuilder, new[] { command }, commandPosition); }
public void AddCommand_does_not_add_command_if_resulting_sql_is_invalid() { var command = new ModificationCommand("T1", null, new ParameterNameGenerator(), p => p.Relational(), new TypedValueBufferFactoryFactory()); var batch = new ModificationCommandBatchFake(); batch.AddCommand(command); batch.ShouldAddCommand = true; batch.ShouldValidateSql = false; batch.AddCommand(command); Assert.Equal(1, batch.ModificationCommands.Count); Assert.Equal(".", batch.CommandText); }
public void AddCommand_adds_command_if_possible() { var command = new ModificationCommand("T1", null, new ParameterNameGenerator(), p => p.Relational(), new TypedValueBufferFactoryFactory()); var batch = new ModificationCommandBatchFake(); batch.AddCommand(command); batch.ShouldAddCommand = true; batch.ShouldValidateSql = true; batch.AddCommand(command); Assert.Equal(2, batch.ModificationCommands.Count); Assert.Same(command, batch.ModificationCommands[0]); Assert.Equal("..", batch.CommandText); }
public async Task ExecuteAsync_executes_batch_commands_and_consumes_reader() { var stateEntry = CreateStateEntry(EntityState.Added); var command = new ModificationCommand("T1", null, new ParameterNameGenerator()); command.AddStateEntry(stateEntry); var mockReader = CreateDataReaderMock(); var batch = new ModificationCommandBatchFake(mockReader.Object); batch.AddCommand(command, new Mock<SqlGenerator> { CallBase = true }.Object); await batch.ExecuteAsync(new Mock<RelationalTransaction>().Object, new RelationalTypeMapper()); mockReader.Verify(r => r.ReadAsync(It.IsAny<CancellationToken>()), Times.Exactly(1)); mockReader.Verify(r => r.NextResultAsync(It.IsAny<CancellationToken>()), Times.Once); }
public void GenerateCommandText_compiles_deletes() { var stateEntry = CreateStateEntry(EntityState.Deleted); var command = new ModificationCommand("T1", null, new ParameterNameGenerator()); command.AddStateEntry(stateEntry); var sqlGeneratorMock = new Mock<SqlGenerator>(); var batch = new ModificationCommandBatchFake(); batch.AddCommand(command, sqlGeneratorMock.Object); batch.GenerateCommandTextBase(sqlGeneratorMock.Object); sqlGeneratorMock.Verify(g => g.AppendBatchHeader(It.IsAny<StringBuilder>())); sqlGeneratorMock.Verify(g => g.AppendDeleteOperation(It.IsAny<StringBuilder>(), "T1", It.IsAny<IReadOnlyList<ColumnModification>>())); }
public void UpdateCommandText_compiles_inserts() { var entry = CreateEntry(EntityState.Added); var command = new ModificationCommand("T1", null, new ParameterNameGenerator(), p => p.Relational(), new TypedValueBufferFactoryFactory()); command.AddEntry(entry); var sqlGeneratorMock = new Mock<ISqlGenerator>(); var batch = new ModificationCommandBatchFake(sqlGeneratorMock.Object); batch.AddCommand(command); batch.UpdateCachedCommandTextBase(0); sqlGeneratorMock.Verify(g => g.AppendBatchHeader(It.IsAny<StringBuilder>())); sqlGeneratorMock.Verify(g => g.AppendInsertOperation(It.IsAny<StringBuilder>(), command)); }
protected override bool CanAddCommand(ModificationCommand modificationCommand) { if (_maxBatchSize <= ModificationCommands.Count) { return false; } var additionalParameterCount = CountParameters(modificationCommand); if (_parameterCount + additionalParameterCount >= MaxParameterCount) { return false; } _parameterCount += additionalParameterCount; return true; }
private int CountParameters(ModificationCommand modificationCommand) { var parameterCount = 0; foreach (var columnModification in modificationCommand.ColumnModifications) { if (columnModification.ParameterName != null) { parameterCount++; } if (columnModification.OriginalParameterName != null) { parameterCount++; } } return parameterCount; }
private ModificationCommandBatch StartNewBatch(ParameterNameGenerator parameterNameGenerator, ModificationCommand modificationCommand) { parameterNameGenerator.Reset(); var batch = _modificationCommandBatchFactory.Create(); batch.AddCommand(modificationCommand); return(batch); }
protected override bool CanAddCommand(ModificationCommand modificationCommand) => ShouldAddCommand;
/// <summary> /// 恢复 /// </summary> /// <param name="relationalReader">关系DataReader</param> protected override void Consume(RelationalDataReader relationalReader) { int commandPosition = 0; int rowsAffected = 0; try { if (Check.IsTraceEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Trace, OracleTraceTag.Entry, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.Consume); } while (true) { if (commandPosition < CommandResultSet.Count && CommandResultSet[commandPosition] == ResultSetMapping.NoResultSet) { commandPosition++; } else { if (commandPosition < CommandResultSet.Count) { if (ModificationCommands[commandPosition].RequiresResultPropagation) { rowsAffected = 0; do { ModificationCommand modificationCommand = ModificationCommands[commandPosition]; if (!relationalReader.Read()) { throw new DbUpdateConcurrencyException(RelationalStrings.UpdateConcurrencyException(ModificationCommands.Count((ModificationCommand m) => m.RequiresResultPropagation), rowsAffected), ModificationCommands[commandPosition].Entries); } IRelationalValueBufferFactory relationalValueBufferFactory = CreateValueBufferFactory(modificationCommand.ColumnModifications); modificationCommand.PropagateResults(relationalValueBufferFactory.Create(relationalReader.DbDataReader)); rowsAffected++; foreach (ColumnModification columnModification in modificationCommand.ColumnModifications) { if (Check.IsTraceEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Trace, OracleTraceTag.SQL, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.Consume, $"Column Name: {columnModification.ColumnName}"); } } }while (++commandPosition < CommandResultSet.Count && CommandResultSet[commandPosition - 1] == ResultSetMapping.NotLastInResultSet); } else { int expectedRowsAffected = 1; while (++commandPosition < CommandResultSet.Count && CommandResultSet[commandPosition - 1] == ResultSetMapping.NotLastInResultSet) { expectedRowsAffected++; } if (!relationalReader.Read()) { break; } rowsAffected = relationalReader.DbDataReader.GetInt32(0); if (rowsAffected != expectedRowsAffected) { throw new DbUpdateConcurrencyException(RelationalStrings.UpdateConcurrencyException(expectedRowsAffected, rowsAffected), ModificationCommands[commandPosition - 1].Entries); } } } if (commandPosition >= CommandResultSet.Count || !relationalReader.DbDataReader.NextResult()) { return; } } } throw new DbUpdateConcurrencyException(RelationalStrings.UpdateConcurrencyException(1, 0), ModificationCommands[commandPosition - 1].Entries); } catch (DbUpdateException dbEx) { if (Check.IsErrorEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Error, OracleTraceTag.Error, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.Consume, dbEx.ToString()); } throw; } catch (Exception ex) { if (Check.IsErrorEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Error, OracleTraceTag.Error, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.Consume, ex.ToString()); } throw new DbUpdateException(RelationalStrings.UpdateStoreException, ex, ModificationCommands[commandPosition - 1].Entries); } }
public void Compare_returns_0_only_for_commands_that_are_equal() { var model = new Entity.Metadata.Model(); var entityType = model.AddEntityType(typeof(object)); var optionsBuilder = new EntityOptionsBuilder() .UseModel(model); optionsBuilder.UseInMemoryStore(persist: false); var contextServices = ((IAccessor <IServiceProvider>) new DbContext(optionsBuilder.Options)).Service; var stateManager = contextServices.GetRequiredService <IStateManager>(); var key = entityType.GetOrAddProperty("Id", typeof(int), shadowProperty: true); entityType.GetOrSetPrimaryKey(key); var entry1 = stateManager.GetOrCreateEntry(new object()); entry1[key] = 1; entry1.SetEntityState(EntityState.Added); var modificationCommandAdded = new ModificationCommand("A", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()); modificationCommandAdded.AddEntry(entry1); var entry2 = stateManager.GetOrCreateEntry(new object()); entry2[key] = 2; entry2.SetEntityState(EntityState.Modified); var modificationCommandModified = new ModificationCommand("A", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()); modificationCommandModified.AddEntry(entry2); var entry3 = stateManager.GetOrCreateEntry(new object()); entry3[key] = 3; entry3.SetEntityState(EntityState.Deleted); var modificationCommandDeleted = new ModificationCommand("A", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()); modificationCommandDeleted.AddEntry(entry3); var mCC = new ModificationCommandComparer(); Assert.True(0 == mCC.Compare(modificationCommandAdded, modificationCommandAdded)); Assert.True(0 == mCC.Compare(null, null)); Assert.True(0 == mCC.Compare( new ModificationCommand("A", "dbo", new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()), new ModificationCommand("A", "dbo", new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()))); Assert.True(0 > mCC.Compare(null, new ModificationCommand("A", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()))); Assert.True(0 < mCC.Compare(new ModificationCommand("A", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()), null)); Assert.True(0 > mCC.Compare( new ModificationCommand("A", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()), new ModificationCommand("A", "dbo", new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()))); Assert.True(0 < mCC.Compare( new ModificationCommand("A", "dbo", new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()), new ModificationCommand("A", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()))); Assert.True(0 > mCC.Compare( new ModificationCommand("A", "dbo", new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()), new ModificationCommand("A", "foo", new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()))); Assert.True(0 < mCC.Compare( new ModificationCommand("A", "foo", new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()), new ModificationCommand("A", "dbo", new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()))); Assert.True(0 > mCC.Compare( new ModificationCommand("A", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()), new ModificationCommand("B", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()))); Assert.True(0 < mCC.Compare( new ModificationCommand("B", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()), new ModificationCommand("A", null, new ParameterNameGenerator(), p => p.Relational(), new UntypedValueBufferFactoryFactory()))); Assert.True(0 > mCC.Compare(modificationCommandModified, modificationCommandAdded)); Assert.True(0 < mCC.Compare(modificationCommandAdded, modificationCommandModified)); Assert.True(0 > mCC.Compare(modificationCommandDeleted, modificationCommandAdded)); Assert.True(0 < mCC.Compare(modificationCommandAdded, modificationCommandDeleted)); Assert.True(0 > mCC.Compare(modificationCommandDeleted, modificationCommandModified)); Assert.True(0 < mCC.Compare(modificationCommandModified, modificationCommandDeleted)); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected virtual IEnumerable <ModificationCommand> CreateModificationCommands( IList <IUpdateEntry> entries, IUpdateAdapter updateAdapter, Func <string> generateParameterName) { var commands = new List <ModificationCommand>(); Dictionary <(string Name, string?Schema), SharedTableEntryMap <ModificationCommand> >?sharedTablesCommandsMap = null; foreach (var entry in entries) { if (entry.SharedIdentityEntry != null && entry.EntityState == EntityState.Deleted) { continue; } var mappings = (IReadOnlyCollection <ITableMapping>)entry.EntityType.GetTableMappings(); var mappingCount = mappings.Count; ModificationCommand?firstCommand = null; foreach (var mapping in mappings) { var table = mapping.Table; var tableKey = (table.Name, table.Schema); ModificationCommand command; var isMainEntry = true; if (table.IsShared) { if (sharedTablesCommandsMap == null) { sharedTablesCommandsMap = new Dictionary <(string, string?), SharedTableEntryMap <ModificationCommand> >(); } if (!sharedTablesCommandsMap.TryGetValue(tableKey, out var sharedCommandsMap)) { sharedCommandsMap = new SharedTableEntryMap <ModificationCommand>(table, updateAdapter); sharedTablesCommandsMap.Add(tableKey, sharedCommandsMap); } command = sharedCommandsMap.GetOrAddValue( entry, (n, s, c) => new ModificationCommand(n, s, generateParameterName, _sensitiveLoggingEnabled, c, Dependencies.UpdateLogger)); isMainEntry = sharedCommandsMap.IsMainEntry(entry); } else { command = new ModificationCommand( table.Name, table.Schema, generateParameterName, _sensitiveLoggingEnabled, comparer: null, Dependencies.UpdateLogger); } command.AddEntry(entry, isMainEntry); commands.Add(command); if (firstCommand == null) { Check.DebugAssert(firstCommand == null, "firstCommand == null"); firstCommand = command; } } if (firstCommand == null) { throw new InvalidOperationException(RelationalStrings.ReadonlyEntitySaved(entry.EntityType.DisplayName())); } } if (sharedTablesCommandsMap != null) { AddUnchangedSharingEntries(sharedTablesCommandsMap.Values, entries); } return(commands); }
public void UpdateCommandText_compiles_multiple_commands() { var entry = CreateEntry(EntityState.Added); var command = new ModificationCommand("T1", null, new ParameterNameGenerator(), p => p.Relational(), new TypedValueBufferFactoryFactory()); command.AddEntry(entry); var fakeSqlGenerator = new FakeSqlGenerator(); var batch = new ModificationCommandBatchFake(fakeSqlGenerator); batch.AddCommand(command); batch.AddCommand(command); Assert.Equal("..", batch.CommandText); Assert.Equal(1, fakeSqlGenerator.AppendBatchHeaderCalls); }
public async Task ExecuteAsync_executes_batch_commands_and_consumes_reader() { var entry = CreateEntry(EntityState.Added); var command = new ModificationCommand("T1", null, new ParameterNameGenerator(), p => p.Relational(), new TypedValueBufferFactoryFactory()); command.AddEntry(entry); var mockReader = CreateDataReaderMock(); var batch = new ModificationCommandBatchFake(mockReader.Object); batch.AddCommand(command); var transactionMock = new Mock<RelationalTransaction>( Mock.Of<IRelationalConnection>(), Mock.Of<DbTransaction>(), false, Mock.Of<ILogger>()); await batch.ExecuteAsync(transactionMock.Object, new RelationalTypeMapper(), new Mock<DbContext>().Object, new Mock<ILogger>().Object); mockReader.Verify(r => r.ReadAsync(It.IsAny<CancellationToken>()), Times.Once); mockReader.Verify(r => r.GetInt32(0), Times.Once); }
public override ResultSetMapping AppendUpdateOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) { Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); Check.NotNull(command, nameof(command)); var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToArray(); var conditionOperations = operations.Where(o => o.IsCondition).ToArray(); var readOperations = operations.Where(o => o.IsRead).ToArray(); if (readOperations.Length > 0) { AppendDeclareTable(commandStringBuilder, "@inserted" + commandPosition, readOperations); } AppendUpdateCommandHeader(commandStringBuilder, name, schema, writeOperations); if (readOperations.Length > 0) { AppendOutputClause(commandStringBuilder, readOperations, "@inserted" + commandPosition); } AppendWhereClause(commandStringBuilder, conditionOperations); commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator); if (readOperations.Length > 0) { return(AppendSelectCommand(commandStringBuilder, readOperations, "@inserted" + commandPosition)); } commandStringBuilder.AppendLine(); return(AppendSelectAffectedCountCommand(commandStringBuilder, name, schema, commandPosition)); }
public async Task ExecuteAsync_saves_store_generated_values_when_updating() { var entry = CreateEntry( EntityState.Modified, generateKeyValues: true, computeNonKeyValue: true); var command = new ModificationCommand("T1", null, new ParameterNameGenerator(), p => p.Relational(), new TypedValueBufferFactoryFactory()); command.AddEntry(entry); var batch = new ModificationCommandBatchFake(CreateDataReaderMock(new[] { "Col2" }, new List<object[]> { new object[] { "FortyTwo" } }).Object); batch.AddCommand(command); var transactionMock = new Mock<RelationalTransaction>( Mock.Of<IRelationalConnection>(), Mock.Of<DbTransaction>(), false, Mock.Of<ILogger>()); await batch.ExecuteAsync(transactionMock.Object, new RelationalTypeMapper(), new Mock<DbContext>().Object, new Mock<ILogger>().Object); Assert.Equal(1, entry[entry.EntityType.GetProperty("Id")]); Assert.Equal("FortyTwo", entry[entry.EntityType.GetProperty("Name")]); }
public async Task ExecuteAsync_saves_store_generated_values() { var stateEntry = CreateStateEntry(EntityState.Added, ValueGenerationOnSave.WhenInserting); var command = new ModificationCommand("T1", null, new ParameterNameGenerator()); command.AddStateEntry(stateEntry); var batch = new ModificationCommandBatchFake(CreateDataReaderMock(new[] { "Col1" }, new List<object[]> { new object[] { 42 } }).Object); batch.AddCommand(command, new Mock<SqlGenerator> { CallBase = true }.Object); await batch.ExecuteAsync(new Mock<RelationalTransaction>().Object, new RelationalTypeMapper()); Assert.Equal(42, stateEntry[stateEntry.EntityType.GetProperty("Id")]); Assert.Equal("Test", stateEntry[stateEntry.EntityType.GetProperty("Name")]); }
public async Task Exception_not_thrown_for_more_than_one_row_returned_for_single_command() { var entry = CreateEntry(EntityState.Added, generateKeyValues: true); entry.MarkAsTemporary(entry.EntityType.GetPrimaryKey().Properties[0]); var command = new ModificationCommand("T1", null, new ParameterNameGenerator(), p => p.Relational(), new TypedValueBufferFactoryFactory()); command.AddEntry(entry); var mockReader = CreateDataReaderMock(new[] { "Col1" }, new List<object[]> { new object[] { 42 }, new object[] { 43 } }); var batch = new ModificationCommandBatchFake(mockReader.Object); batch.AddCommand(command); var transactionMock = new Mock<RelationalTransaction>( Mock.Of<IRelationalConnection>(), Mock.Of<DbTransaction>(), false, Mock.Of<ILogger>()); await batch.ExecuteAsync(transactionMock.Object, new RelationalTypeMapper(), new Mock<DbContext>().Object, new Mock<ILogger>().Object); Assert.Equal(42, entry[entry.EntityType.GetProperty("Id")]); }
public async Task Exception_thrown_if_no_rows_returned_for_command_with_store_generated_values() { var stateEntry = CreateStateEntry(EntityState.Added, ValueGenerationOnSave.WhenInserting); var command = new ModificationCommand("T1", null, new ParameterNameGenerator()); command.AddStateEntry(stateEntry); var batch = new ModificationCommandBatchFake(CreateDataReaderMock(new[] { "Col1" }, new List<object[]>()).Object); batch.AddCommand(command, new Mock<SqlGenerator> { CallBase = true }.Object); Assert.Equal(Strings.FormatUpdateConcurrencyException(1, 0), (await Assert.ThrowsAsync<DbUpdateConcurrencyException>( async () => await batch.ExecuteAsync(new Mock<RelationalTransaction>().Object, new RelationalTypeMapper()))).Message); }
public async Task Exception_not_thrown_for_more_than_one_row_returned_for_single_command() { var stateEntry = CreateStateEntry(EntityState.Added, ValueGenerationOnSave.WhenInserting); var command = new ModificationCommand("T1", null, new ParameterNameGenerator()); command.AddStateEntry(stateEntry); var mockReader = CreateDataReaderMock(new[] { "Col1" }, new List<object[]> { new object[] { 42 }, new object[] { 43 } }); var batch = new ModificationCommandBatchFake(mockReader.Object); batch.AddCommand(command, new Mock<SqlGenerator> { CallBase = true }.Object); await batch.ExecuteAsync(new Mock<RelationalTransaction>().Object, new RelationalTypeMapper()); Assert.Equal(42, stateEntry[stateEntry.EntityType.GetProperty("Id")]); }
protected override bool CanAddCommand(ModificationCommand modificationCommand) { // TODO: check this return(true); }
public override ResultSetMapping AppendUpdateOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) { Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); Check.NotNull(command, nameof(command)); var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToArray(); var conditionOperations = operations.Where(o => o.IsCondition).ToArray(); var readOperations = operations.Where(o => o.IsRead).ToArray(); if (readOperations.Length > 0) { AppendDeclareTable(commandStringBuilder, InsertedTableBaseName, commandPosition, readOperations); } AppendUpdateCommandHeader(commandStringBuilder, name, schema, writeOperations); if (readOperations.Length > 0) { AppendOutputClause(commandStringBuilder, readOperations, InsertedTableBaseName, commandPosition); } AppendWhereClause(commandStringBuilder, conditionOperations); commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator); if (readOperations.Length > 0) { return AppendSelectCommand(commandStringBuilder, readOperations, InsertedTableBaseName, commandPosition); } commandStringBuilder.AppendLine(); return AppendSelectAffectedCountCommand(commandStringBuilder, name, schema, commandPosition); }
public virtual void AppendUpdateOperation(StringBuilder commandStringBuilder, ModificationCommand command) { Check.NotNull(command, nameof(command)); var tableName = command.TableName; var schemaName = command.SchemaName; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToArray(); var conditionOperations = operations.Where(o => o.IsCondition).ToArray(); var readOperations = operations.Where(o => o.IsRead).ToArray(); AppendUpdateCommand(commandStringBuilder, tableName, schemaName, writeOperations, conditionOperations); if (readOperations.Length > 0) { var keyOperations = operations.Where(o => o.IsKey).ToArray(); AppendSelectAffectedCommand(commandStringBuilder, tableName, schemaName, readOperations, keyOperations); } else { AppendSelectAffectedCountCommand(commandStringBuilder, tableName, schemaName); } }
private static void AddMatchingPredecessorEdge( Dictionary<IKeyValueIndex, List<ModificationCommand>> predecessorsMap, IKeyValueIndex dependentKeyValue, Multigraph<ModificationCommand, IForeignKey> commandGraph, ModificationCommand command, IForeignKey foreignKey) { List<ModificationCommand> predecessorCommands; if (predecessorsMap.TryGetValue(dependentKeyValue, out predecessorCommands)) { foreach (var predecessor in predecessorCommands) { if (predecessor != command) { commandGraph.AddEdge(predecessor, command, foreignKey); } } } }
public override void AppendInsertOperation(StringBuilder commandStringBuilder, ModificationCommand command) { if (AppendInsertOperationCallback != null) { AppendInsertOperationCallback(commandStringBuilder, command); } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected virtual IEnumerable<ModificationCommand> CreateModificationCommands( [NotNull] IReadOnlyList<IUpdateEntry> entries, [NotNull] Func<string> generateParameterName) { // TODO: Handle multiple state entries that update the same row Func<IProperty, IRelationalPropertyAnnotations> getAnnotationsDelegate = _annotationProvider.For; foreach (var entry in entries) { var command = new ModificationCommand( _annotationProvider.For(entry.EntityType).TableName, _annotationProvider.For(entry.EntityType).Schema, generateParameterName, getAnnotationsDelegate); command.AddEntry(entry); if (command.EntityState != EntityState.Modified || command.ColumnModifications.Any(m => m.IsWrite)) { yield return command; } } }
private void Format(IForeignKey foreignKey, ModificationCommand source, ModificationCommand target, StringBuilder builder) { var reverseDependency = !source.Entries.Any(e => foreignKey.DeclaringEntityType.IsAssignableFrom(e.EntityType)); if (reverseDependency) { builder.Append(" <-"); } builder.Append(" "); if (foreignKey.DependentToPrincipal != null || foreignKey.PrincipalToDependent != null) { if (!reverseDependency && foreignKey.DependentToPrincipal != null) { builder.Append(foreignKey.DependentToPrincipal.Name); builder.Append(" "); } if (foreignKey.PrincipalToDependent != null) { builder.Append(foreignKey.PrincipalToDependent.Name); builder.Append(" "); } if (reverseDependency && foreignKey.DependentToPrincipal != null) { builder.Append(foreignKey.DependentToPrincipal.Name); builder.Append(" "); } } else { builder.Append("ForeignKey "); } var dependentCommand = reverseDependency ? target : source; var dependentEntry = dependentCommand.Entries.First(e => foreignKey.DeclaringEntityType.IsAssignableFrom(e.EntityType)); builder.Append("{ "); for (var i = 0; i < foreignKey.Properties.Count; i++) { var property = foreignKey.Properties[i]; builder.Append("'"); builder.Append(property.Name); builder.Append("'"); if (_sensitiveLoggingEnabled) { builder.Append(": "); builder.Append(dependentEntry.GetCurrentValue(property)); } if (i != foreignKey.Properties.Count - 1) { builder.Append(", "); } } builder.Append(" } "); if (!reverseDependency) { builder.Append("<- "); } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected override bool CanAddCommand(ModificationCommand modificationCommand) { return(ModificationCommands.Count == 0); }
public async Task Exception_thrown_if_no_rows_returned_for_command_with_store_generated_values() { var entry = CreateEntry(EntityState.Added, generateKeyValues: true); entry.MarkAsTemporary(entry.EntityType.GetPrimaryKey().Properties[0]); var command = new ModificationCommand("T1", null, new ParameterNameGenerator(), p => p.Relational(), new TypedValueBufferFactoryFactory()); command.AddEntry(entry); var batch = new ModificationCommandBatchFake(CreateDataReaderMock(new[] { "Col1" }, new List<object[]>()).Object); batch.AddCommand(command); var transactionMock = new Mock<RelationalTransaction>( Mock.Of<IRelationalConnection>(), Mock.Of<DbTransaction>(), false, Mock.Of<ILogger>()); Assert.Equal(Strings.UpdateConcurrencyException(1, 0), (await Assert.ThrowsAsync<DbUpdateConcurrencyException>( async () => await batch.ExecuteAsync( transactionMock.Object, new RelationalTypeMapper(), new Mock<DbContext>().Object, new Mock<ILogger>().Object))).Message); }
protected override bool CanAddCommand(ModificationCommand modificationCommand) => ModificationCommands.Count == 0;
/// <summary> /// 异步恢复 /// </summary> /// <param name="relationalReader">关系DataReader</param> /// <param name="cancellationToken">取消令牌</param> /// <returns></returns> protected override async Task ConsumeAsync(RelationalDataReader relationalReader, CancellationToken cancellationToken = default(CancellationToken)) { int commandPosition = 0; try { if (Check.IsTraceEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Trace, OracleTraceTag.Entry, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.ConsumeAsync); } while (true) { if (commandPosition < CommandResultSet.Count && CommandResultSet[commandPosition] == ResultSetMapping.NoResultSet) { commandPosition++; } else { if (commandPosition < CommandResultSet.Count) { if (ModificationCommands[commandPosition].RequiresResultPropagation) { int rowsAffected = 0; int num = 0; do { ModificationCommand tableModification = ModificationCommands[commandPosition]; if (!(await relationalReader.ReadAsync(cancellationToken))) { throw new DbUpdateConcurrencyException(RelationalStrings.UpdateConcurrencyException(ModificationCommands.Count((ModificationCommand m) => m.RequiresResultPropagation), rowsAffected), ModificationCommands[commandPosition].Entries); } IRelationalValueBufferFactory relationalValueBufferFactory = CreateValueBufferFactory(tableModification.ColumnModifications); tableModification.PropagateResults(relationalValueBufferFactory.Create(relationalReader.DbDataReader)); rowsAffected++; num = commandPosition + 1; commandPosition = num; }while (num < CommandResultSet.Count && CommandResultSet[commandPosition - 1] == ResultSetMapping.NotLastInResultSet); } else { int expectedRowsAffected = 1; while (true) { int num = commandPosition + 1; commandPosition = num; if (num >= CommandResultSet.Count || CommandResultSet[commandPosition - 1] != ResultSetMapping.NotLastInResultSet) { break; } expectedRowsAffected++; } if (!relationalReader.Read()) { break; } int rowsAffected = relationalReader.DbDataReader.GetInt32(0); if (rowsAffected != expectedRowsAffected) { throw new DbUpdateConcurrencyException(RelationalStrings.UpdateConcurrencyException(expectedRowsAffected, rowsAffected), ModificationCommands[commandPosition - 1].Entries); } } } bool flag = commandPosition < CommandResultSet.Count; if (flag) { flag = await relationalReader.DbDataReader.NextResultAsync(cancellationToken); } if (!flag) { return; } } } throw new DbUpdateConcurrencyException(RelationalStrings.UpdateConcurrencyException(1, 0), ModificationCommands[commandPosition - 1].Entries); } catch (DbUpdateException dbEx) { if (Check.IsErrorEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Error, OracleTraceTag.Error, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.ConsumeAsync, dbEx.ToString()); } throw; } catch (Exception ex) { if (Check.IsErrorEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Error, OracleTraceTag.Error, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.ConsumeAsync, ex.ToString()); } throw new DbUpdateException(RelationalStrings.UpdateStoreException, ex, ModificationCommands[commandPosition].Entries); } }
public void Compare_returns_0_only_for_commands_that_are_equal() { var model = new Model(); var entityType = model.AddEntityType(typeof(object)); var optionsBuilder = new DbContextOptionsBuilder() .UseModel(model); optionsBuilder.UseInMemoryDatabase(); var contextServices = new DbContext(optionsBuilder.Options).GetInfrastructure(); var stateManager = contextServices.GetRequiredService <IStateManager>(); var key = entityType.AddProperty("Id", typeof(int)); entityType.GetOrSetPrimaryKey(key); var entry1 = stateManager.GetOrCreateEntry(new object()); entry1[key] = 1; entry1.SetEntityState(EntityState.Added); var modificationCommandAdded = new ModificationCommand("A", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()); modificationCommandAdded.AddEntry(entry1); var entry2 = stateManager.GetOrCreateEntry(new object()); entry2[key] = 2; entry2.SetEntityState(EntityState.Modified); var modificationCommandModified = new ModificationCommand("A", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()); modificationCommandModified.AddEntry(entry2); var entry3 = stateManager.GetOrCreateEntry(new object()); entry3[key] = 3; entry3.SetEntityState(EntityState.Deleted); var modificationCommandDeleted = new ModificationCommand("A", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()); modificationCommandDeleted.AddEntry(entry3); var mCC = new ModificationCommandComparer(); Assert.True(0 == mCC.Compare(modificationCommandAdded, modificationCommandAdded)); Assert.True(0 == mCC.Compare(null, null)); Assert.True(0 == mCC.Compare( new ModificationCommand("A", "dbo", new ParameterNameGenerator().GenerateNext, p => p.TestProvider()), new ModificationCommand("A", "dbo", new ParameterNameGenerator().GenerateNext, p => p.TestProvider()))); Assert.True(0 > mCC.Compare(null, new ModificationCommand("A", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()))); Assert.True(0 < mCC.Compare(new ModificationCommand("A", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()), null)); Assert.True(0 > mCC.Compare( new ModificationCommand("A", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()), new ModificationCommand("A", "dbo", new ParameterNameGenerator().GenerateNext, p => p.TestProvider()))); Assert.True(0 < mCC.Compare( new ModificationCommand("A", "dbo", new ParameterNameGenerator().GenerateNext, p => p.TestProvider()), new ModificationCommand("A", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()))); Assert.True(0 > mCC.Compare( new ModificationCommand("A", "dbo", new ParameterNameGenerator().GenerateNext, p => p.TestProvider()), new ModificationCommand("A", "foo", new ParameterNameGenerator().GenerateNext, p => p.TestProvider()))); Assert.True(0 < mCC.Compare( new ModificationCommand("A", "foo", new ParameterNameGenerator().GenerateNext, p => p.TestProvider()), new ModificationCommand("A", "dbo", new ParameterNameGenerator().GenerateNext, p => p.TestProvider()))); Assert.True(0 > mCC.Compare( new ModificationCommand("A", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()), new ModificationCommand("B", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()))); Assert.True(0 < mCC.Compare( new ModificationCommand("B", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()), new ModificationCommand("A", null, new ParameterNameGenerator().GenerateNext, p => p.TestProvider()))); Assert.True(0 > mCC.Compare(modificationCommandModified, modificationCommandAdded)); Assert.True(0 < mCC.Compare(modificationCommandAdded, modificationCommandModified)); Assert.True(0 > mCC.Compare(modificationCommandDeleted, modificationCommandAdded)); Assert.True(0 < mCC.Compare(modificationCommandAdded, modificationCommandDeleted)); Assert.True(0 > mCC.Compare(modificationCommandDeleted, modificationCommandModified)); Assert.True(0 < mCC.Compare(modificationCommandModified, modificationCommandDeleted)); }
public override ResultSetMapping AppendInsertOperation( StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) => AppendInsertOperation(commandStringBuilder, command, commandPosition, false);
public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) { var sqlGenerationHelper = (IFbSqlGenerationHelper)SqlGenerationHelper; var name = command.TableName; var operations = command.ColumnModifications; var conditionOperations = operations.Where(o => o.IsCondition).ToList(); var inputOperations = conditionOperations; commandStringBuilder.Append("EXECUTE BLOCK ("); commandStringBuilder.AppendJoin(inputOperations, (b, e) => { var type = GetColumnType(e); var parameterName = e.UseOriginalValueParameter ? e.OriginalParameterName : e.ParameterName; b.Append(parameterName); b.Append(" "); b.Append(type); b.Append(" = ?"); }, ", "); commandStringBuilder.AppendLine(")"); commandStringBuilder.AppendLine($"RETURNS (RowsAffected {_typeReturn})"); commandStringBuilder.AppendLine("AS"); commandStringBuilder.AppendLine("BEGIN"); var oldParameterNameMarker = sqlGenerationHelper.ParameterName; sqlGenerationHelper.ParameterName = ":"; try { AppendDeleteCommandHeader(commandStringBuilder, name, null); AppendWhereClause(commandStringBuilder, conditionOperations); } finally { sqlGenerationHelper.ParameterName = oldParameterNameMarker; } commandStringBuilder .Append(SqlGenerationHelper.StatementTerminator) .AppendLine(); commandStringBuilder.AppendLine(); commandStringBuilder.AppendLine("RowsAffected = ROW_COUNT;"); commandStringBuilder.AppendLine("SUSPEND;"); commandStringBuilder.Append("END"); commandStringBuilder .Append(SqlGenerationHelper.StatementTerminator) .AppendLine(); return(ResultSetMapping.LastInResultSet); }
public override ResultSetMapping AppendInsertOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) { if (!string.IsNullOrEmpty(command.Schema)) { commandStringBuilder.Append(command.Schema + "."); } commandStringBuilder.Append(command.TableName); return(ResultSetMapping.NotLastInResultSet); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected virtual IEnumerable <ModificationCommand> CreateModificationCommands( [NotNull] IList <IUpdateEntry> entries, [NotNull] Func <string> generateParameterName) { var commands = new List <ModificationCommand>(); if (_sharedTableEntryMapFactories == null) { _sharedTableEntryMapFactories = SharedTableEntryMap <ModificationCommand> .CreateSharedTableEntryMapFactories(entries[0].EntityType.Model, StateManager); } Dictionary <(string Schema, string Name), SharedTableEntryMap <ModificationCommand> > sharedTablesCommandsMap = null; foreach (var entry in entries) { if (entry.SharedIdentityEntry != null && entry.EntityState == EntityState.Deleted) { continue; } var entityType = entry.EntityType; var relationalExtensions = entityType.Relational(); var table = relationalExtensions.TableName; var schema = relationalExtensions.Schema; var tableKey = (schema, table); ModificationCommand command; if (_sharedTableEntryMapFactories.TryGetValue(tableKey, out var commandIdentityMapFactory)) { if (sharedTablesCommandsMap == null) { sharedTablesCommandsMap = new Dictionary <(string Schema, string Name), SharedTableEntryMap <ModificationCommand> >(); } if (!sharedTablesCommandsMap.TryGetValue(tableKey, out var sharedCommandsMap)) { sharedCommandsMap = commandIdentityMapFactory( (t, s, c) => new ModificationCommand( t, s, generateParameterName, _sensitiveLoggingEnabled, c)); sharedTablesCommandsMap.Add((schema, table), sharedCommandsMap); } command = sharedCommandsMap.GetOrAddValue(entry); } else { command = new ModificationCommand( table, schema, generateParameterName, _sensitiveLoggingEnabled, comparer: null); } command.AddEntry(entry); commands.Add(command); } if (sharedTablesCommandsMap != null) { Validate(sharedTablesCommandsMap); AddUnchangedSharingEntries(sharedTablesCommandsMap, entries); } return(commands.Where( c => c.EntityState != EntityState.Modified || c.ColumnModifications.Any(m => m.IsWrite))); }
private static bool CanBeInsertedInSameStatement(ModificationCommand firstCommand, ModificationCommand secondCommand) => string.Equals(firstCommand.TableName, secondCommand.TableName, StringComparison.Ordinal) && string.Equals(firstCommand.Schema, secondCommand.Schema, StringComparison.Ordinal) && firstCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName).SequenceEqual( secondCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName)) && firstCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName).SequenceEqual( secondCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName));
protected override bool CanAddCommand(ModificationCommand modificationCommand) { return(ModificationCommands.Count < _maxBatchSize); }
public override void AppendInsertOperation(StringBuilder commandStringBuilder, ModificationCommand command) { if (!string.IsNullOrEmpty(command.SchemaName)) { commandStringBuilder.Append(command.SchemaName + "."); } commandStringBuilder.Append(command.TableName); }
public virtual void AppendDeleteOperation(StringBuilder commandStringBuilder, ModificationCommand command) { Check.NotNull(command, nameof(command)); var tableName = command.TableName; var schemaName = command.SchemaName; var conditionOperations = command.ColumnModifications.Where(o => o.IsCondition).ToArray(); AppendDeleteCommand(commandStringBuilder, tableName, schemaName, conditionOperations); AppendSelectAffectedCountCommand(commandStringBuilder, tableName, schemaName); }
public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) { var sqlGenerationHelper = (IFbSqlGenerationHelper)SqlGenerationHelper; var name = command.TableName; var operations = command.ColumnModifications; var conditionOperations = operations.Where(o => o.IsCondition).ToList(); var inputOperations = GenerateParameters(conditionOperations); commandStringBuilder.Append("EXECUTE BLOCK ("); commandStringBuilder.AppendJoin(inputOperations, (b, p) => { b.Append(p.name); b.Append(" "); b.Append(p.type); b.Append(" = ?"); }, ", "); commandStringBuilder.AppendLine(")"); commandStringBuilder.AppendLine("RETURNS (ROWS_AFFECTED INT)"); commandStringBuilder.AppendLine("AS"); commandStringBuilder.AppendLine("BEGIN"); var oldParameterNameMarker = sqlGenerationHelper.ParameterNameMarker; sqlGenerationHelper.ParameterNameMarker = ":"; try { AppendDeleteCommandHeader(commandStringBuilder, name, null); AppendWhereClause(commandStringBuilder, conditionOperations); } finally { sqlGenerationHelper.ParameterNameMarker = oldParameterNameMarker; } commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); commandStringBuilder.AppendLine(); commandStringBuilder.AppendLine("ROWS_AFFECTED = ROW_COUNT;"); commandStringBuilder.AppendLine("SUSPEND;"); commandStringBuilder.AppendLine("END"); commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); return(ResultSetMapping.LastInResultSet); }
private static int CountParameters(ModificationCommand modificationCommand) { var parameterCount = 0; foreach (var columnModification in modificationCommand.ColumnModifications) { if (columnModification.UseCurrentValueParameter) { parameterCount++; } if (columnModification.UseOriginalValueParameter) { parameterCount++; } } return parameterCount; }
public override ResultSetMapping AppendInsertOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) { var result = ResultSetMapping.NoResultSet; var name = command.TableName; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToList(); var readOperations = operations.Where(o => o.IsRead).ToList(); var anyRead = readOperations.Any(); AppendInsertCommandHeader(commandStringBuilder, name, null, writeOperations); AppendValuesHeader(commandStringBuilder, writeOperations); AppendValues(commandStringBuilder, writeOperations); if (anyRead) { commandStringBuilder.AppendLine(); commandStringBuilder.Append("RETURNING "); commandStringBuilder.AppendJoin(readOperations, (b, e) => { b.Append(SqlGenerationHelper.DelimitIdentifier(e.ColumnName)); }, ", "); result = ResultSetMapping.LastInResultSet; } commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); return(result); }
protected override bool CanAddCommand(ModificationCommand modificationCommand) { return(ShouldAddCommand); }
public override ResultSetMapping AppendUpdateOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) { var sqlGenerationHelper = (IFbSqlGenerationHelper)SqlGenerationHelper; var name = command.TableName; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToList(); var readOperations = operations.Where(o => o.IsRead).ToList(); var conditionOperations = operations.Where(o => o.IsCondition).ToList(); var inputOperations = GenerateParameters(operations.Where(o => o.IsWrite || o.IsCondition)).ToList(); var anyRead = readOperations.Any(); commandStringBuilder.Append("EXECUTE BLOCK ("); commandStringBuilder.AppendJoin(inputOperations, (b, p) => { b.Append(p.name); b.Append(" "); b.Append(p.type); b.Append(" = ?"); }, ", "); commandStringBuilder.AppendLine(")"); commandStringBuilder.Append("RETURNS ("); if (anyRead) { commandStringBuilder.AppendJoin(readOperations, (b, e) => { var type = GetColumnType(e); b.Append(SqlGenerationHelper.DelimitIdentifier(e.ColumnName)); b.Append(" "); b.Append(type); }, ", "); } else { commandStringBuilder.Append("ROWS_AFFECTED INT"); } commandStringBuilder.AppendLine(")"); commandStringBuilder.AppendLine("AS"); commandStringBuilder.AppendLine("BEGIN"); var oldParameterNameMarker = sqlGenerationHelper.ParameterNameMarker; sqlGenerationHelper.ParameterNameMarker = ":"; try { AppendUpdateCommandHeader(commandStringBuilder, name, null, writeOperations); AppendWhereClause(commandStringBuilder, conditionOperations); } finally { sqlGenerationHelper.ParameterNameMarker = oldParameterNameMarker; } if (anyRead) { commandStringBuilder.AppendLine(); commandStringBuilder.Append("RETURNING "); commandStringBuilder.AppendJoin(readOperations, (b, e) => { b.Append(SqlGenerationHelper.DelimitIdentifier(e.ColumnName)); }, ", "); commandStringBuilder.Append(" INTO "); commandStringBuilder.AppendJoin(readOperations, (b, e) => { b.Append(" :"); b.Append(SqlGenerationHelper.DelimitIdentifier(e.ColumnName)); }, ", "); } commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); if (!anyRead) { commandStringBuilder.AppendLine("ROWS_AFFECTED = ROW_COUNT;"); commandStringBuilder.AppendLine("SUSPEND;"); } else { commandStringBuilder.AppendLine("IF (ROW_COUNT > 0) THEN"); commandStringBuilder.AppendLine("SUSPEND;"); } commandStringBuilder.AppendLine("END"); commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); return(ResultSetMapping.LastInResultSet); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected virtual IEnumerable <ModificationCommand> CreateModificationCommands( [NotNull] IList <IUpdateEntry> entries, [NotNull] IUpdateAdapter updateAdapter, [NotNull] Func <string> generateParameterName) { var commands = new List <ModificationCommand>(); if (_sharedTableEntryMapFactories == null) { _sharedTableEntryMapFactories = SharedTableEntryMap <ModificationCommand> .CreateSharedTableEntryMapFactories(updateAdapter.Model, updateAdapter); } Dictionary <(string Name, string Schema), SharedTableEntryMap <ModificationCommand> > sharedTablesCommandsMap = null; foreach (var entry in entries) { if (entry.SharedIdentityEntry != null && entry.EntityState == EntityState.Deleted) { continue; } var entityType = entry.EntityType; var table = entityType.GetTableName(); var schema = entityType.GetSchema(); var tableKey = (table, schema); ModificationCommand command; var isMainEntry = true; if (_sharedTableEntryMapFactories.TryGetValue(tableKey, out var commandIdentityMapFactory)) { if (sharedTablesCommandsMap == null) { sharedTablesCommandsMap = new Dictionary <(string, string), SharedTableEntryMap <ModificationCommand> >(); } if (!sharedTablesCommandsMap.TryGetValue(tableKey, out var sharedCommandsMap)) { sharedCommandsMap = commandIdentityMapFactory( (n, s, c) => new ModificationCommand( n, s, generateParameterName, _sensitiveLoggingEnabled, c)); sharedTablesCommandsMap.Add(tableKey, sharedCommandsMap); } command = sharedCommandsMap.GetOrAddValue(entry); isMainEntry = sharedCommandsMap.IsMainEntityType(entry.EntityType.GetRootType()); } else { command = new ModificationCommand( table, schema, generateParameterName, _sensitiveLoggingEnabled, comparer: null); } command.AddEntry(entry, isMainEntry); commands.Add(command); } if (sharedTablesCommandsMap != null) { AddUnchangedSharingEntries(sharedTablesCommandsMap.Values, entries); } return(commands.Where( c => c.EntityState != EntityState.Modified || c.ColumnModifications.Any(m => m.IsWrite))); }
/// <summary> /// </summary> /// <param name="modificationCommand"></param> /// <returns></returns> public override bool AddCommand(ModificationCommand modificationCommand) { _modificationCommands.Add(modificationCommand); return(true); }
private bool CanBeInsertedInSameStatement(ModificationCommand firstCommand, ModificationCommand secondCommand) => string.Equals(firstCommand.TableName, secondCommand.TableName, StringComparison.Ordinal) && string.Equals(firstCommand.Schema, secondCommand.Schema, StringComparison.Ordinal) && firstCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName).SequenceEqual( secondCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName)) && firstCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName).SequenceEqual( secondCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName));
/// <summary> /// 更新缓存命令文本 /// </summary> /// <param name="commandPosition"></param> protected override void UpdateCachedCommandText(int commandPosition) { try { if (Check.IsTraceEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Trace, OracleTraceTag.Entry, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.UpdateCachedCommandText); } new StringBuilder(); // The list of conceptual insert/update/delete // Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ModificationCommandss // in the batch. // 取得待处理的插入/更新/删除行的概念性命令,这意味着你应该对真实的执行命令自己进行组装 ModificationCommand modificationCommand = ModificationCommands[commandPosition]; // 对命令进行组装 if (modificationCommand.EntityState == EntityState.Added) { // Add命令 if (_batchInsertCommands.Count > 0 && !CanBeInserted(_batchInsertCommands.First().Key, modificationCommand)) { CachedCommandText.Append(GetBatchInsertCommandText(commandPosition)); _batchInsertCommands.Clear(); } if (ModificationCommands[commandPosition].ColumnModifications.Where((ColumnModification o) => o.IsRead).ToArray().Length != 0) { _batchInsertCommands.Add(modificationCommand, _cursorPosition); _cursorPosition++; } else { _batchInsertCommands.Add(modificationCommand, 0); } LastCachedCommandIndex = commandPosition; } else if (modificationCommand.EntityState == EntityState.Deleted) { // Delete命令 CachedCommandText.Append(GetBatchDeleteCommandText(commandPosition)); LastCachedCommandIndex = commandPosition; } else { // Update命令 CachedCommandText.Append(GetBatchUpdateCommandText(commandPosition)); LastCachedCommandIndex = commandPosition; } } catch (Exception ex) { if (Check.IsErrorEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Error, OracleTraceTag.Error, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.UpdateCachedCommandText, ex.ToString()); } throw; } finally { if (Check.IsTraceEnabled(m_oracleLogger?.Logger)) { Trace <DbLoggerCategory.Update> .Write(m_oracleLogger, LogLevel.Trace, OracleTraceTag.Exit, OracleTraceClassName.OracleModificationCommandBatch, OracleTraceFuncName.UpdateCachedCommandText); } } }
public void Compare_returns_0_only_for_commands_that_are_equal() { var mCC = new ModificationCommandComparer(); var configuration = new DbContext(new DbContextOptions().UseInMemoryStore(persist: false)).Configuration; var entityType1 = new EntityType(typeof(object)); var key1 = entityType1.GetOrAddProperty("Id", typeof(int), shadowProperty: true); entityType1.GetOrSetPrimaryKey(key1); var stateEntry1 = new MixedStateEntry(configuration, entityType1, new object()); stateEntry1[key1] = 0; stateEntry1.EntityState = EntityState.Added; var modificationCommandAdded = new ModificationCommand(new SchemaQualifiedName("A"), new ParameterNameGenerator()); modificationCommandAdded.AddStateEntry(stateEntry1); var entityType2 = new EntityType(typeof(object)); var key2 = entityType2.GetOrAddProperty("Id", typeof(int), shadowProperty: true); entityType2.GetOrSetPrimaryKey(key2); var stateEntry2 = new MixedStateEntry(configuration, entityType2, new object()); stateEntry2[key2] = 0; stateEntry2.EntityState = EntityState.Modified; var modificationCommandModified = new ModificationCommand(new SchemaQualifiedName("A"), new ParameterNameGenerator()); modificationCommandModified.AddStateEntry(stateEntry2); var entityType3 = new EntityType(typeof(object)); var key3 = entityType3.GetOrAddProperty("Id", typeof(int), shadowProperty: true); entityType3.GetOrSetPrimaryKey(key3); var stateEntry3 = new MixedStateEntry(configuration, entityType3, new object()); stateEntry3[key3] = 0; stateEntry3.EntityState = EntityState.Deleted; var modificationCommandDeleted = new ModificationCommand(new SchemaQualifiedName("A"), new ParameterNameGenerator()); modificationCommandDeleted.AddStateEntry(stateEntry3); Assert.True(0 == mCC.Compare(modificationCommandAdded, modificationCommandAdded)); Assert.True(0 == mCC.Compare(null, null)); Assert.True(0 == mCC.Compare( new ModificationCommand(new SchemaQualifiedName("A", "dbo"), new ParameterNameGenerator()), new ModificationCommand(new SchemaQualifiedName("A", "dbo"), new ParameterNameGenerator()))); Assert.True(0 > mCC.Compare(null, new ModificationCommand(new SchemaQualifiedName("A"), new ParameterNameGenerator()))); Assert.True(0 < mCC.Compare(new ModificationCommand(new SchemaQualifiedName("A"), new ParameterNameGenerator()), null)); Assert.True(0 > mCC.Compare( new ModificationCommand(new SchemaQualifiedName("A"), new ParameterNameGenerator()), new ModificationCommand(new SchemaQualifiedName("A", "dbo"), new ParameterNameGenerator()))); Assert.True(0 < mCC.Compare( new ModificationCommand(new SchemaQualifiedName("A", "dbo"), new ParameterNameGenerator()), new ModificationCommand(new SchemaQualifiedName("A"), new ParameterNameGenerator()))); Assert.True(0 > mCC.Compare( new ModificationCommand(new SchemaQualifiedName("A", "dbo"), new ParameterNameGenerator()), new ModificationCommand(new SchemaQualifiedName("A", "foo"), new ParameterNameGenerator()))); Assert.True(0 < mCC.Compare( new ModificationCommand(new SchemaQualifiedName("A", "foo"), new ParameterNameGenerator()), new ModificationCommand(new SchemaQualifiedName("A", "dbo"), new ParameterNameGenerator()))); Assert.True(0 > mCC.Compare( new ModificationCommand(new SchemaQualifiedName("A"), new ParameterNameGenerator()), new ModificationCommand(new SchemaQualifiedName("B"), new ParameterNameGenerator()))); Assert.True(0 < mCC.Compare( new ModificationCommand(new SchemaQualifiedName("B"), new ParameterNameGenerator()), new ModificationCommand(new SchemaQualifiedName("A"), new ParameterNameGenerator()))); Assert.True(0 > mCC.Compare(modificationCommandModified, modificationCommandAdded)); Assert.True(0 < mCC.Compare(modificationCommandAdded, modificationCommandModified)); Assert.True(0 > mCC.Compare(modificationCommandDeleted, modificationCommandAdded)); Assert.True(0 < mCC.Compare(modificationCommandAdded, modificationCommandDeleted)); Assert.True(0 > mCC.Compare(modificationCommandDeleted, modificationCommandModified)); Assert.True(0 < mCC.Compare(modificationCommandModified, modificationCommandDeleted)); }
protected override bool CanAddCommand(ModificationCommand modificationCommand) { return ShouldAddCommand; }