/// <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);
            }
        }
Exemplo n.º 3
0
        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));
            }
        }