/// <summary> /// Adds an <see cref="IUpdateEntry" /> to this command representing an entity to be inserted, updated, or deleted. /// </summary> /// <param name="entry"> The entry representing the entity to add. </param> public virtual void AddEntry([NotNull] IUpdateEntry entry) { Check.NotNull(entry, nameof(entry)); switch (entry.EntityState) { case EntityState.Deleted: case EntityState.Modified: case EntityState.Added: break; default: throw new ArgumentException(RelationalStrings.ModificationCommandInvalidEntityState(entry.EntityState)); } if (_entries.Count > 0) { var lastEntry = _entries[_entries.Count - 1]; var lastEntryState = lastEntry.SharedIdentityEntry == null ? lastEntry.EntityState : EntityState.Modified; var entryState = entry.SharedIdentityEntry == null ? entry.EntityState : EntityState.Modified; if (lastEntryState != entryState) { if (_sensitiveLoggingEnabled) { throw new InvalidOperationException( RelationalStrings.ConflictingRowUpdateTypesSensitive( entry.EntityType.DisplayName(), entry.BuildCurrentValuesString(entry.EntityType.FindPrimaryKey().Properties), entryState, lastEntry.EntityType.DisplayName(), lastEntry.BuildCurrentValuesString(lastEntry.EntityType.FindPrimaryKey().Properties), lastEntryState)); } throw new InvalidOperationException( RelationalStrings.ConflictingRowUpdateTypes( entry.EntityType.DisplayName(), entryState, lastEntry.EntityType.DisplayName(), lastEntryState)); } } _entries.Add(entry); _columnModifications = null; }
public void BatchCommands_throws_on_conflicting_updates_for_shared_table_added_entities(bool sensitiveLogging) { var currentDbContext = CreateContextServices(CreateSharedTableModel()).GetRequiredService <ICurrentDbContext>(); var stateManager = currentDbContext.GetDependencies().StateManager; var first = new FakeEntity { Id = 42, Value = "Test" }; var firstEntry = stateManager.GetOrCreateEntry(first); firstEntry.SetEntityState(EntityState.Added); var second = new RelatedFakeEntity { Id = 42 }; var secondEntry = stateManager.GetOrCreateEntry(second); secondEntry.SetEntityState(EntityState.Deleted); if (sensitiveLogging) { Assert.Equal( RelationalStrings.ConflictingRowUpdateTypesSensitive( nameof(RelatedFakeEntity), "{Id: 42}", EntityState.Deleted, nameof(FakeEntity), "{Id: 42}", EntityState.Added), Assert.Throws <InvalidOperationException>( () => CreateCommandBatchPreparer(stateManager: stateManager, sensitiveLogging: true) .BatchCommands(new[] { firstEntry, secondEntry }).ToArray()).Message); } else { Assert.Equal( RelationalStrings.ConflictingRowUpdateTypes( nameof(RelatedFakeEntity), EntityState.Deleted, nameof(FakeEntity), EntityState.Added), Assert.Throws <InvalidOperationException>( () => CreateCommandBatchPreparer(stateManager: stateManager, sensitiveLogging: false) .BatchCommands(new[] { firstEntry, secondEntry }).ToArray()).Message); } }
private void ValidateState(IUpdateEntry mainEntry, IUpdateEntry entry) { var mainEntryState = mainEntry.SharedIdentityEntry == null ? mainEntry.EntityState : EntityState.Modified; if (mainEntryState == EntityState.Modified) { return; } var entryState = entry.SharedIdentityEntry == null ? entry.EntityState : EntityState.Modified; if (mainEntryState != entryState) { if (_sensitiveLoggingEnabled) { throw new InvalidOperationException( RelationalStrings.ConflictingRowUpdateTypesSensitive( entry.EntityType.DisplayName(), entry.BuildCurrentValuesString(entry.EntityType.FindPrimaryKey().Properties), entryState, mainEntry.EntityType.DisplayName(), mainEntry.BuildCurrentValuesString(mainEntry.EntityType.FindPrimaryKey().Properties), mainEntryState)); } throw new InvalidOperationException( RelationalStrings.ConflictingRowUpdateTypes( entry.EntityType.DisplayName(), entryState, mainEntry.EntityType.DisplayName(), mainEntryState)); } }