/// <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)
        {
            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)
            {
                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);
            }

            return(commands.Where(
                       c => c.EntityState != EntityState.Modified ||
                       c.ColumnModifications.Any(m => m.IsWrite)));
        }
Example #2
0
        /// <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>
        ///     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 mappings     = (IReadOnlyCollection <ITableMapping>)entry.EntityType.GetTableMappings();
                var mappingCount = mappings.Count;
                ModificationCommand mainCommand = null;
                var relatedCommands             = mappingCount > 1 ? new List <ModificationCommand>(mappingCount - 1) : null;
                foreach (var mapping in mappings)
                {
                    var table    = mapping.Table;
                    var tableKey = (table.Name, 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.IsMainEntry(entry);
                    }
                    else
                    {
                        command = new ModificationCommand(
                            table.Name, table.Schema, generateParameterName, _sensitiveLoggingEnabled, comparer: null);
                    }

                    command.AddEntry(entry, isMainEntry);
                    commands.Add(command);

                    if (mapping.IsMainTableMapping)
                    {
                        Check.DebugAssert(mainCommand == null, "mainCommand == null");
                        mainCommand = command;
                    }
                    else if (relatedCommands != null)
                    {
                        relatedCommands.Add(command);
                    }
                }

                if (mainCommand == null)
                {
                    throw new InvalidOperationException(RelationalStrings.ReadonlyEntitySaved(entry.EntityType.DisplayName()));
                }

                if (relatedCommands != null)
                {
                    foreach (var relatedCommand in relatedCommands)
                    {
                        relatedCommand.Predecessor = mainCommand;
                    }
                }
            }

            if (sharedTablesCommandsMap != null)
            {
                AddUnchangedSharingEntries(sharedTablesCommandsMap.Values, entries);
            }

            return(commands);
        }