public virtual void Detects_duplicate_foreignKey_names_within_hierarchy_with_different_column_order()
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <Animal>();
            modelBuilder.Entity <Cat>(
                et =>
            {
                et.Property(c => c.Breed).HasColumnName("Breed");
                et.HasOne <Person>().WithMany()
                .HasForeignKey(
                    c => new { c.Name, c.Breed })
                .HasPrincipalKey(
                    p => new { p.Name, p.FavoriteBreed })
                .HasConstraintName("FK");
            });
            modelBuilder.Entity <Dog>(
                et =>
            {
                et.Property(c => c.Breed).HasColumnName("Breed");
                et.HasOne <Person>().WithMany()
                .HasForeignKey(
                    d => new { d.Breed, d.Name })
                .HasPrincipalKey(
                    p => new { p.FavoriteBreed, p.Name })
                .HasConstraintName("FK");
            });

            VerifyError(
                RelationalStrings.DuplicateForeignKeyColumnMismatch(
                    "{'" + nameof(Dog.Breed) + "', '" + nameof(Dog.Name) + "'}", nameof(Dog),
                    "{'" + nameof(Cat.Name) + "', '" + nameof(Cat.Breed) + "'}", nameof(Cat),
                    nameof(Animal), "FK",
                    "{'" + nameof(Dog.Breed) + "', '" + nameof(Dog.Name) + "'}",
                    "{'" + nameof(Cat.Name) + "', '" + nameof(Cat.Breed) + "'}"),
                modelBuilder.Model);
        }
Exemplo n.º 2
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));
            }
        }
Exemplo n.º 3
0
        protected virtual bool CanSetDefaultValue([CanBeNull] object value)
        {
            if (GetDefaultValue(false) == value)
            {
                return(true);
            }

            if (!Annotations.CanSetAnnotation(
                    RelationalFullAnnotationNames.Instance.DefaultValue,
                    ProviderFullAnnotationNames?.DefaultValue,
                    value))
            {
                return(false);
            }

            if (ShouldThrowOnConflict)
            {
                if (GetDefaultValueSql(false) != null)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.ConflictingColumnServerGeneration(nameof(DefaultValue), Property.Name, nameof(DefaultValueSql)));
                }
                if (GetComputedColumnSql(false) != null)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.ConflictingColumnServerGeneration(nameof(DefaultValue), Property.Name, nameof(ComputedColumnSql)));
                }
            }
            else if (value != null &&
                     (!CanSetDefaultValueSql(null) ||
                      !CanSetComputedColumnSql(null)))
            {
                return(false);
            }

            return(true);
        }
Exemplo n.º 4
0
                private DbCommand CreateCommand(
                    IRelationalConnection connection,
                    IReadOnlyDictionary <string, object> parameterValues)
                {
                    var command = connection.DbConnection.CreateCommand();

                    ((OracleCommand)command).BindByName = true;

                    command.CommandText = CommandText;

                    if (connection.CurrentTransaction != null)
                    {
                        command.Transaction = connection.CurrentTransaction.GetDbTransaction();
                    }

                    if (connection.CommandTimeout != null)
                    {
                        command.CommandTimeout = (int)connection.CommandTimeout;
                    }

                    if (Parameters.Count > 0)
                    {
                        if (parameterValues == null)
                        {
                            throw new InvalidOperationException(
                                      RelationalStrings.MissingParameterValue(
                                          Parameters[0].InvariantName));
                        }

                        foreach (var parameter in Parameters)
                        {
                            parameter.AddDbParameter(command, parameterValues);
                        }
                    }

                    return(command);
                }
        public virtual void Detects_duplicate_index_names_within_hierarchy_with_different_column_order()
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <Animal>();
            modelBuilder.Entity <Cat>(
                et =>
            {
                et.Property(c => c.Breed).HasColumnName("Breed");
                et.HasIndex(
                    c => new
                {
                    c.Name,
                    c.Breed
                }).HasName("IX");
            });
            modelBuilder.Entity <Dog>(
                et =>
            {
                et.Property(c => c.Breed).HasColumnName("Breed");
                et.HasIndex(
                    d => new
                {
                    d.Breed,
                    d.Name
                }).HasName("IX");
            });

            VerifyError(
                RelationalStrings.DuplicateIndexColumnMismatch(
                    "{'" + nameof(Dog.Breed) + "', '" + nameof(Dog.Name) + "'}", nameof(Dog),
                    "{'" + nameof(Cat.Name) + "', '" + nameof(Cat.Breed) + "'}", nameof(Cat),
                    nameof(Animal), "IX",
                    "{'" + nameof(Dog.Breed) + "', '" + nameof(Dog.Name) + "'}",
                    "{'" + nameof(Cat.Name) + "', '" + nameof(Cat.Breed) + "'}"),
                modelBuilder.Model);
        }
Exemplo n.º 6
0
        /// <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 DbCommand CreateCommand(
            IRelationalConnection connection,
            IReadOnlyDictionary <string, object> parameterValues)
        {
            var command = connection.DbConnection.CreateCommand();

            command.CommandText = AdjustCommandText(CommandText);

            ConfigureCommand(command);

            if (connection.CurrentTransaction != null)
            {
                command.Transaction = connection.CurrentTransaction.GetDbTransaction();
            }

            if (connection.CommandTimeout != null)
            {
                command.CommandTimeout = (int)connection.CommandTimeout;
            }

            if (Parameters.Count > 0)
            {
                if (parameterValues == null)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.MissingParameterValue(
                                  Parameters[0].InvariantName));
                }

                foreach (var parameter in Parameters)
                {
                    parameter.AddDbParameter(command, parameterValues);
                }
            }

            return(command);
        }
Exemplo n.º 7
0
        public virtual EntityProjectionExpression UpdateEntityType([NotNull] IEntityType derivedType)
        {
            Check.NotNull(derivedType, nameof(derivedType));

            if (!derivedType.GetAllBaseTypes().Contains(EntityType))
            {
                throw new InvalidOperationException(
                          RelationalStrings.InvalidDerivedTypeInEntityProjection(
                              derivedType.DisplayName(), EntityType.DisplayName()));
            }

            var propertyExpressionMap = new Dictionary <IProperty, ColumnExpression>();

            foreach (var kvp in _propertyExpressionMap)
            {
                var property = kvp.Key;
                if (derivedType.IsAssignableFrom(property.DeclaringEntityType) ||
                    property.DeclaringEntityType.IsAssignableFrom(derivedType))
                {
                    propertyExpressionMap[property] = kvp.Value;
                }
            }

            var discriminatorExpression = DiscriminatorExpression;

            if (DiscriminatorExpression is CaseExpression caseExpression)
            {
                var entityTypesToSelect = derivedType.GetTptDiscriminatorValues();
                var whenClauses         = caseExpression.WhenClauses
                                          .Where(wc => entityTypesToSelect.Contains((string)((SqlConstantExpression)wc.Result).Value !))
                                          .ToList();

                discriminatorExpression = caseExpression.Update(operand: null, whenClauses, elseResult: null);
            }

            return(new EntityProjectionExpression(derivedType, propertyExpressionMap, discriminatorExpression));
        }
Exemplo n.º 8
0
        public void Inserts_are_batched_only_when_necessary(int minBatchSize)
        {
            var expectedBlogs = new List <Blog>();

            TestHelpers.ExecuteWithStrategyInTransaction(
                () => (BloggingContext)Fixture.CreateContext(minBatchSize),
                UseTransaction,
                context =>
            {
                var owner = new Owner();
                context.Owners.Add(owner);

                for (var i = 1; i < 4; i++)
                {
                    var blog = new Blog
                    {
                        Id    = Guid.NewGuid(),
                        Owner = owner
                    };

                    context.Set <Blog>().Add(blog);
                    expectedBlogs.Add(blog);
                }

                Fixture.TestSqlLoggerFactory.Clear();

                context.SaveChanges();

                Assert.Contains(
                    minBatchSize == 3
                            ? RelationalStrings.LogBatchReadyForExecution(new TestLogger <SqlServerLoggingDefinitions>()).GenerateMessage(3)
                            : RelationalStrings.LogBatchSmallerThanMinBatchSize(new TestLogger <SqlServerLoggingDefinitions>()).GenerateMessage(3, 4),
                    Fixture.TestSqlLoggerFactory.Log.Select(l => l.Message));

                Assert.Equal(minBatchSize <= 3 ? 2 : 4, Fixture.TestSqlLoggerFactory.SqlStatements.Count);
            }, context => AssertDatabaseState(context, false, expectedBlogs));
        }
Exemplo n.º 9
0
        /// <summary>
        ///     Asynchronously opens the connection to the database.
        /// </summary>
        /// <param name="cancellationToken">
        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
        /// </param>
        /// <returns> A task that represents the asynchronous operation. </returns>
        public virtual async Task OpenAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            CheckForAmbientTransactions();

            if (_connection.Value.State == ConnectionState.Broken)
            {
                _connection.Value.Close();
            }

            if (_connection.Value.State != ConnectionState.Open)
            {
                _logger.LogDebug(
                    RelationalEventId.OpeningConnection,
                    new
                {
                    _connection.Value.Database,
                    _connection.Value.DataSource
                },
                    state =>
                    RelationalStrings.RelationalLoggerOpeningConnection(
                        state.Database,
                        state.DataSource));

                await _connection.Value.OpenAsync(cancellationToken);

                if (_openedCount == 0)
                {
                    _openedInternally = true;
                    _openedCount++;
                }
            }
            else
            {
                _openedCount++;
            }
        }
        public async Task Throws_when_parameters_are_configured_and_value_is_missing(
            Delegate commandDelegate,
            string telemetryName,
            bool async)
        {
            var fakeConnection = CreateConnection();

            var relationalCommand = CreateRelationalCommand(
                parameters: new[]
            {
                new TypeMappedRelationalParameter("FirstInvariant", "FirstParameter", new RelationalTypeMapping("int", typeof(int), DbType.Int32), false),
                new TypeMappedRelationalParameter("SecondInvariant", "SecondParameter", new RelationalTypeMapping("long", typeof(long), DbType.Int64), true),
                new TypeMappedRelationalParameter("ThirdInvariant", "ThirdParameter", RelationalTypeMapping.NullMapping, null)
            });

            var parameterValues = new Dictionary <string, object>
            {
                { "FirstInvariant", 17 },
                { "SecondInvariant", 18L }
            };

            if (async)
            {
                Assert.Equal(
                    RelationalStrings.MissingParameterValue("ThirdInvariant"),
                    (await Assert.ThrowsAsync <InvalidOperationException>(async()
                                                                          => await((CommandFunc)commandDelegate)(fakeConnection, relationalCommand, parameterValues))).Message);
            }
            else
            {
                Assert.Equal(
                    RelationalStrings.MissingParameterValue("ThirdInvariant"),
                    Assert.Throws <InvalidOperationException>(()
                                                              => ((CommandAction)commandDelegate)(fakeConnection, relationalCommand, parameterValues)).Message);
            }
        }
Exemplo n.º 11
0
        public virtual void AddEntry([NotNull] IUpdateEntry entry)
        {
            Check.NotNull(entry, nameof(entry));

            if ((entry.EntityState != EntityState.Added) &&
                (entry.EntityState != EntityState.Modified) &&
                (entry.EntityState != EntityState.Deleted))
            {
                throw new ArgumentException(RelationalStrings.ModificationFunctionInvalidEntityState(entry.EntityState));
            }

            var firstEntry = _entries.FirstOrDefault();

            if ((firstEntry != null) &&
                (firstEntry.EntityState != entry.EntityState))
            {
                throw new InvalidOperationException(RelationalStrings.ConflictingRowUpdates);

                // TODO: Check for any other conflicts between the two entries
            }

            _entries.Add(entry);
            _columnModifications = null;
        }
Exemplo n.º 12
0
        /// <summary>
        ///     Validates the mapping/configuration of functions in the model.
        /// </summary>
        /// <param name="model"> The model to validate. </param>
        /// <param name="logger"> The logger to use. </param>
        protected virtual void ValidateDbFunctions([NotNull] IModel model, [NotNull] IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
        {
            foreach (var dbFunction in model.GetDbFunctions())
            {
                var methodInfo = dbFunction.MethodInfo;

                if (string.IsNullOrEmpty(dbFunction.FunctionName))
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DbFunctionNameEmpty(methodInfo.DisplayName()));
                }

                if (dbFunction.Translation == null)
                {
                    if (RelationalDependencies.TypeMappingSource.FindMapping(methodInfo.ReturnType) == null)
                    {
                        throw new InvalidOperationException(
                                  RelationalStrings.DbFunctionInvalidReturnType(
                                      methodInfo.DisplayName(),
                                      methodInfo.ReturnType.ShortDisplayName()));
                    }

                    foreach (var parameter in methodInfo.GetParameters())
                    {
                        if (RelationalDependencies.TypeMappingSource.FindMapping(parameter.ParameterType) == null)
                        {
                            throw new InvalidOperationException(
                                      RelationalStrings.DbFunctionInvalidParameterType(
                                          parameter.Name,
                                          methodInfo.DisplayName(),
                                          parameter.ParameterType.ShortDisplayName()));
                        }
                    }
                }
            }
        }
Exemplo n.º 13
0
        public void DbFunction_Queryable_custom_translation()
        {
            var modelBuilder      = GetModelBuilder();
            var methodInfo        = typeof(TestMethods).GetMethod(nameof(TestMethods.MethodJ));
            var dbFunctionBuilder = modelBuilder.HasDbFunction(methodInfo);

            Assert.False(dbFunctionBuilder.GetInfrastructure()
                         .CanSetTranslation(args => new SqlFragmentExpression("Empty"), fromDataAnnotation: true));
            Assert.Null(dbFunctionBuilder.Metadata.Translation);

            dbFunctionBuilder.GetInfrastructure().HasTranslation(args => new SqlFragmentExpression("Empty"));
            Assert.Null(dbFunctionBuilder.Metadata.Translation);

            dbFunctionBuilder.GetInfrastructure()
            .HasTranslation(args => new SqlFragmentExpression("Empty"), fromDataAnnotation: true);
            Assert.Null(dbFunctionBuilder.Metadata.Translation);

            Assert.Equal(RelationalStrings.DbFunctionQueryableCustomTranslation(methodInfo.DisplayName()),
                         Assert.Throws <InvalidOperationException>(
                             () => dbFunctionBuilder.HasTranslation(args => new SqlFragmentExpression("Empty"))).Message);

            var dbFunction = dbFunctionBuilder.Metadata;

            Assert.Equal(RelationalStrings.DbFunctionQueryableCustomTranslation(methodInfo.DisplayName()),
                         Assert.Throws <InvalidOperationException>(
                             () => ((IConventionDbFunction)dbFunction).SetTranslation(args => new SqlFragmentExpression("Empty"))).Message);

            Assert.Equal(RelationalStrings.DbFunctionQueryableCustomTranslation(methodInfo.DisplayName()),
                         Assert.Throws <InvalidOperationException>(
                             () => ((IConventionDbFunction)dbFunction)
                             .SetTranslation(args => new SqlFragmentExpression("Empty"), fromDataAnnotation: true)).Message);

            Assert.Equal(RelationalStrings.DbFunctionQueryableCustomTranslation(methodInfo.DisplayName()),
                         Assert.Throws <InvalidOperationException>(
                             () => dbFunction.Translation = args => new SqlFragmentExpression("Empty")).Message);
        }
Exemplo n.º 14
0
        public virtual void Detects_duplicate_foreignKey_names_within_hierarchy_with_different_uniqueness()
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <Animal>();
            var fk1 = modelBuilder.Entity <Cat>().HasOne <Person>().WithMany().HasForeignKey(c => c.Name).HasPrincipalKey(p => p.Name)
                      .HasConstraintName("FK_Animal_Person_Name").Metadata;
            var fk2 = modelBuilder.Entity <Dog>().HasOne <Person>().WithOne().HasForeignKey <Dog>(d => d.Name)
                      .HasPrincipalKey <Person>(p => p.Name)
                      .HasConstraintName("FK_Animal_Person_Name").Metadata;

            VerifyError(
                RelationalStrings.DuplicateForeignKeyUniquenessMismatch(
                    "{'" + nameof(Dog.Name) + "'}", nameof(Dog),
                    "{'" + nameof(Cat.Name) + "'}", nameof(Cat),
                    nameof(Animal), "FK_Animal_Person_Name"),
                modelBuilder.Model);

            var index1 = fk1.DeclaringEntityType.GetDeclaredIndexes().Single();
            var index2 = fk2.DeclaringEntityType.GetDeclaredIndexes().Single();

            Assert.NotSame(index1, index2);
            Assert.NotEqual(index1.GetName(), index2.GetName());
        }
        /// <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>
        public override void AddDbParameter(DbCommand command, object value)
        {
            Check.NotNull(command, nameof(command));
            Check.NotNull(value, nameof(value));

            if (value is object[] innerValues)
            {
                if (innerValues.Length < RelationalParameters.Count)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.MissingParameterValue(
                                  RelationalParameters[innerValues.Length].InvariantName));
                }

                for (var i = 0; i < RelationalParameters.Count; i++)
                {
                    RelationalParameters[i].AddDbParameter(command, innerValues[i]);
                }
            }
            else
            {
                throw new InvalidOperationException(RelationalStrings.ParameterNotObjectArray(InvariantName));
            }
        }
        public void BatchCommands_throws_on_incomplete_updates_for_shared_table_no_middle_dependent(EntityState state, bool sensitiveLogging)
        {
            var currentDbContext = CreateContextServices(CreateSharedTableModel()).GetRequiredService <ICurrentDbContext>();
            var stateManager     = currentDbContext.GetDependencies().StateManager;

            var first = new FakeEntity {
                Id = 42
            };
            var firstEntry = stateManager.GetOrCreateEntry(first);

            firstEntry.SetEntityState(state);

            var second = new AnotherFakeEntity {
                Id = 42
            };
            var secondEntry = stateManager.GetOrCreateEntry(second);

            secondEntry.SetEntityState(state);

            if (sensitiveLogging)
            {
                Assert.Equal(RelationalStrings.SharedRowEntryCountMismatchSensitive(
                                 nameof(FakeEntity), nameof(FakeEntity), nameof(DerivedRelatedFakeEntity), "Id:42", state),
                             Assert.Throws <InvalidOperationException>(
                                 () => CreateCommandBatchPreparer(currentDbContext: currentDbContext, sensitiveLogging: sensitiveLogging)
                                 .BatchCommands(new[] { firstEntry, secondEntry }).ToArray()).Message);
            }
            else
            {
                Assert.Equal(RelationalStrings.SharedRowEntryCountMismatch(
                                 nameof(FakeEntity), nameof(FakeEntity), nameof(DerivedRelatedFakeEntity), state),
                             Assert.Throws <InvalidOperationException>(
                                 () => CreateCommandBatchPreparer(currentDbContext: currentDbContext, sensitiveLogging: sensitiveLogging)
                                 .BatchCommands(new[] { firstEntry, secondEntry }).ToArray()).Message);
            }
        }
        public virtual async Task Complex_query_with_groupBy_in_subquery4(bool async)
        {
            var message = (await Assert.ThrowsAsync <InvalidOperationException>(
                               () => AssertQuery(
                                   async,
                                   ss => ss.Set <Customer>()
                                   .Select(
                                       c => new
            {
                Key = c.CustomerID,
                Subquery = c.Orders
                           .Select(o => new { First = o.OrderID, Second = o.Customer.City + o.CustomerID })
                           .GroupBy(x => x.Second)
                           .Select(g => new { Sum = g.Sum(x => x.First), Count = g.Count(x => x.Second.StartsWith("Lon")) }).ToList()
            }),
                                   elementSorter: e => e.Key,
                                   elementAsserter: (e, a) =>
            {
                Assert.Equal(e.Key, a.Key);
                AssertCollection(e.Subquery, a.Subquery);
            }))).Message;

            Assert.Equal(RelationalStrings.MissingIdentifyingProjectionInDistinctGroupBySubquery("o.OrderID"), message);
        }
Exemplo n.º 18
0
 /// <summary>
 ///     Closes the connection to the database.
 /// </summary>
 public virtual void Close()
 {
     if (_openedCount > 0 &&
         --_openedCount == 0 &&
         _openedInternally)
     {
         if (_connection.Value.State != ConnectionState.Closed)
         {
             _logger.LogDebug(
                 RelationalEventId.ClosingConnection,
                 new
             {
                 _connection.Value.Database,
                 _connection.Value.DataSource
             },
                 state =>
                 RelationalStrings.RelationalLoggerClosingConnection(
                     state.Database,
                     state.DataSource));
             _connection.Value.Close();
         }
         _openedInternally = false;
     }
 }
        public async Task Exception_thrown_if_rows_returned_for_command_without_store_generated_values_is_not_1()
        {
            var entry = CreateEntry(EntityState.Added);

            var command = new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, true, null);

            command.AddEntry(entry);

            var connection = CreateConnection(
                CreateFakeDataReader(
                    new[] { "Col1" }, new List <object[]>
            {
                new object[] { 42 }
            }));

            var batch = new ModificationCommandBatchFake();

            batch.AddCommand(command);

            Assert.Equal(
                RelationalStrings.UpdateConcurrencyException(1, 42),
                (await Assert.ThrowsAsync <DbUpdateConcurrencyException>(
                     async() => await batch.ExecuteAsync(connection))).Message);
        }
        /// <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>
        public virtual string ResolveConnectionString(string connectionString)
        {
            var connectionName = TryGetConnectionName(connectionString);

            if (connectionName == null)
            {
                return(connectionString);
            }

            var configuration = _options.FindExtension <CoreOptionsExtension>()
                                ?.ApplicationServiceProvider
                                ?.GetService <IConfiguration>();

            var resolved = configuration?[connectionName]
                           ?? configuration?[DefaultSection + connectionName];

            if (resolved == null)
            {
                throw new InvalidOperationException(
                          RelationalStrings.NamedConnectionStringNotFound(connectionName));
            }

            return(resolved);
        }
Exemplo n.º 21
0
        /// <summary>
        ///     Opens the connection to the database.
        /// </summary>
        public virtual void Open()
        {
            CheckForAmbientTransactions();

            if (_connection.Value.State == ConnectionState.Broken)
            {
                _connection.Value.Close();
            }

            if (_connection.Value.State != ConnectionState.Open)
            {
                _logger.LogDebug(
                    RelationalEventId.OpeningConnection,
                    new
                {
                    _connection.Value.Database,
                    _connection.Value.DataSource
                },
                    state =>
                    RelationalStrings.RelationalLoggerOpeningConnection(
                        state.Database,
                        state.DataSource));

                _connection.Value.Open();

                if (_openedCount == 0)
                {
                    _openedInternally = true;
                    _openedCount++;
                }
            }
            else
            {
                _openedCount++;
            }
        }
Exemplo n.º 22
0
        /// <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 void ValidateDbFunctions([NotNull] IModel model)
        {
            foreach (var dbFunction in model.Relational().DbFunctions)
            {
                var methodInfo = dbFunction.MethodInfo;

                if (string.IsNullOrEmpty(dbFunction.FunctionName))
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DbFunctionNameEmpty(methodInfo.DisplayName()));
                }

                if (dbFunction.Translation == null)
                {
                    if (!RelationalDependencies.TypeMapper.IsTypeMapped(methodInfo.ReturnType))
                    {
                        throw new InvalidOperationException(
                                  RelationalStrings.DbFunctionInvalidReturnType(
                                      methodInfo.DisplayName(),
                                      methodInfo.ReturnType.ShortDisplayName()));
                    }

                    foreach (var parameter in methodInfo.GetParameters())
                    {
                        if (!RelationalDependencies.TypeMapper.IsTypeMapped(parameter.ParameterType))
                        {
                            throw new InvalidOperationException(
                                      RelationalStrings.DbFunctionInvalidParameterType(
                                          parameter.Name,
                                          methodInfo.DisplayName(),
                                          parameter.ParameterType.ShortDisplayName()));
                        }
                    }
                }
            }
        }
Exemplo n.º 23
0
        /// <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>
        public virtual string GenerateScript(
            string fromMigration = null,
            string toMigration   = null,
            bool idempotent      = false)
        {
            IEnumerable <string> appliedMigrations;

            if (string.IsNullOrEmpty(fromMigration) ||
                fromMigration == Migration.InitialDatabase)
            {
                appliedMigrations = Enumerable.Empty <string>();
            }
            else
            {
                var fromMigrationId = _migrationsAssembly.GetMigrationId(fromMigration);
                appliedMigrations = _migrationsAssembly.Migrations
                                    .Where(t => string.Compare(t.Key, fromMigrationId, StringComparison.OrdinalIgnoreCase) <= 0)
                                    .Select(t => t.Key);
            }

            IReadOnlyList <Migration> migrationsToApply, migrationsToRevert;

            PopulateMigrations(
                appliedMigrations,
                toMigration,
                out migrationsToApply,
                out migrationsToRevert);

            var builder = new IndentedStringBuilder();

            if (fromMigration == Migration.InitialDatabase ||
                string.IsNullOrEmpty(fromMigration))
            {
                builder.AppendLine(_historyRepository.GetCreateIfNotExistsScript());
                builder.Append(_sqlGenerationHelper.BatchTerminator);
            }

            for (var i = 0; i < migrationsToRevert.Count; i++)
            {
                var migration         = migrationsToRevert[i];
                var previousMigration = i != migrationsToRevert.Count - 1
                    ? migrationsToRevert[i + 1]
                    : null;

                _logger.LogDebug(
                    RelationalEventId.GeneratingMigrationDownScript,
                    () => RelationalStrings.GeneratingDown(migration.GetId()));

                foreach (var command in GenerateDownSql(migration, previousMigration))
                {
                    if (idempotent)
                    {
                        builder.AppendLine(_historyRepository.GetBeginIfExistsScript(migration.GetId()));
                        using (builder.Indent())
                        {
                            builder.AppendLines(command.CommandText);
                        }
                        builder.AppendLine(_historyRepository.GetEndIfScript());
                    }
                    else
                    {
                        builder.AppendLine(command.CommandText);
                    }

                    builder.Append(_sqlGenerationHelper.BatchTerminator);
                }
            }

            foreach (var migration in migrationsToApply)
            {
                _logger.LogDebug(
                    RelationalEventId.GeneratingMigrationUpScript,
                    () => RelationalStrings.GeneratingUp(migration.GetId()));

                foreach (var command in GenerateUpSql(migration))
                {
                    if (idempotent)
                    {
                        builder.AppendLine(_historyRepository.GetBeginIfNotExistsScript(migration.GetId()));
                        using (builder.Indent())
                        {
                            builder.AppendLines(command.CommandText);
                        }
                        builder.AppendLine(_historyRepository.GetEndIfScript());
                    }
                    else
                    {
                        builder.AppendLine(command.CommandText);
                    }

                    builder.Append(_sqlGenerationHelper.BatchTerminator);
                }
            }

            return(builder.ToString());
        }
Exemplo n.º 24
0
        /// <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 void ValidateSharedColumnsCompatibility(
            [NotNull] IReadOnlyList <IEntityType> mappedTypes, [NotNull] string tableName)
        {
            var propertyMappings = new Dictionary <string, IProperty>();

            foreach (var property in mappedTypes.SelectMany(et => et.GetDeclaredProperties()))
            {
                var propertyAnnotations = property.Relational();
                var columnName          = propertyAnnotations.ColumnName;
                if (propertyMappings.TryGetValue(columnName, out var duplicateProperty))
                {
                    var previousAnnotations = duplicateProperty.Relational();
                    var currentTypeString   = propertyAnnotations.ColumnType
                                              ?? TypeMapper.GetMapping(property).StoreType;
                    var previousTypeString = previousAnnotations.ColumnType
                                             ?? TypeMapper.GetMapping(duplicateProperty).StoreType;
                    if (!currentTypeString.Equals(previousTypeString, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new InvalidOperationException(
                                  RelationalStrings.DuplicateColumnNameDataTypeMismatch(
                                      duplicateProperty.DeclaringEntityType.DisplayName(),
                                      duplicateProperty.Name,
                                      property.DeclaringEntityType.DisplayName(),
                                      property.Name,
                                      columnName,
                                      tableName,
                                      previousTypeString,
                                      currentTypeString));
                    }

                    if (property.IsColumnNullable() != duplicateProperty.IsColumnNullable())
                    {
                        throw new InvalidOperationException(
                                  RelationalStrings.DuplicateColumnNameNullabilityMismatch(
                                      duplicateProperty.DeclaringEntityType.DisplayName(),
                                      duplicateProperty.Name,
                                      property.DeclaringEntityType.DisplayName(),
                                      property.Name,
                                      columnName,
                                      tableName));
                    }

                    var currentComputedColumnSql  = propertyAnnotations.ComputedColumnSql ?? "";
                    var previousComputedColumnSql = previousAnnotations.ComputedColumnSql ?? "";
                    if (!currentComputedColumnSql.Equals(previousComputedColumnSql, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new InvalidOperationException(
                                  RelationalStrings.DuplicateColumnNameComputedSqlMismatch(
                                      duplicateProperty.DeclaringEntityType.DisplayName(),
                                      duplicateProperty.Name,
                                      property.DeclaringEntityType.DisplayName(),
                                      property.Name,
                                      columnName,
                                      tableName,
                                      previousComputedColumnSql,
                                      currentComputedColumnSql));
                    }

                    var currentDefaultValue  = propertyAnnotations.DefaultValue;
                    var previousDefaultValue = previousAnnotations.DefaultValue;
                    if (!Equals(currentDefaultValue, previousDefaultValue))
                    {
                        throw new InvalidOperationException(
                                  RelationalStrings.DuplicateColumnNameDefaultSqlMismatch(
                                      duplicateProperty.DeclaringEntityType.DisplayName(),
                                      duplicateProperty.Name,
                                      property.DeclaringEntityType.DisplayName(),
                                      property.Name,
                                      columnName,
                                      tableName,
                                      previousDefaultValue ?? "NULL",
                                      currentDefaultValue ?? "NULL"));
                    }

                    var currentDefaultValueSql  = propertyAnnotations.DefaultValueSql ?? "";
                    var previousDefaultValueSql = previousAnnotations.DefaultValueSql ?? "";
                    if (!currentDefaultValueSql.Equals(previousDefaultValueSql, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new InvalidOperationException(
                                  RelationalStrings.DuplicateColumnNameDefaultSqlMismatch(
                                      duplicateProperty.DeclaringEntityType.DisplayName(),
                                      duplicateProperty.Name,
                                      property.DeclaringEntityType.DisplayName(),
                                      property.Name,
                                      columnName,
                                      tableName,
                                      previousDefaultValueSql,
                                      currentDefaultValueSql));
                    }
                }
                else
                {
                    propertyMappings[columnName] = property;
                }
            }
        }
Exemplo n.º 25
0
        /// <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 void ValidateSharedForeignKeysCompatibility(
            [NotNull] IReadOnlyList <IEntityType> mappedTypes, [NotNull] string tableName)
        {
            var foreignKeyMappings = new Dictionary <string, IForeignKey>();

            foreach (var foreignKey in mappedTypes.SelectMany(et => et.GetDeclaredForeignKeys()))
            {
                var foreignKeyAnnotations = foreignKey.Relational();
                var foreignKeyName        = foreignKeyAnnotations.Name;

                if (!foreignKeyMappings.TryGetValue(foreignKeyName, out var duplicateForeignKey))
                {
                    foreignKeyMappings[foreignKeyName] = foreignKey;
                    continue;
                }

                var principalAnnotations    = foreignKey.PrincipalEntityType.Relational();
                var principalTable          = Format(principalAnnotations.Schema, principalAnnotations.TableName);
                var duplicateAnnotations    = duplicateForeignKey.PrincipalEntityType.Relational();
                var duplicatePrincipalTable = Format(duplicateAnnotations.Schema, duplicateAnnotations.TableName);
                if (!string.Equals(principalTable, duplicatePrincipalTable, StringComparison.OrdinalIgnoreCase))
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyPrincipalTableMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  tableName,
                                  foreignKeyName,
                                  principalTable,
                                  duplicatePrincipalTable));
                }

                if (!foreignKey.Properties.Select(p => p.Relational().ColumnName)
                    .SequenceEqual(duplicateForeignKey.Properties.Select(p => p.Relational().ColumnName)))
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyColumnMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  tableName,
                                  foreignKeyName,
                                  foreignKey.Properties.FormatColumns(),
                                  duplicateForeignKey.Properties.FormatColumns()));
                }

                if (!foreignKey.PrincipalKey.Properties
                    .Select(p => p.Relational().ColumnName)
                    .SequenceEqual(
                        duplicateForeignKey.PrincipalKey.Properties
                        .Select(p => p.Relational().ColumnName)))
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyPrincipalColumnMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  tableName,
                                  foreignKeyName,
                                  foreignKey.PrincipalKey.Properties.FormatColumns(),
                                  duplicateForeignKey.PrincipalKey.Properties.FormatColumns()));
                }

                if (foreignKey.IsUnique != duplicateForeignKey.IsUnique)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyUniquenessMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  tableName,
                                  foreignKeyName));
                }

                if (foreignKey.DeleteBehavior != duplicateForeignKey.DeleteBehavior)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyDeleteBehaviorMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  tableName,
                                  foreignKeyName,
                                  foreignKey.DeleteBehavior,
                                  duplicateForeignKey.DeleteBehavior));
                }
            }
        }
Exemplo n.º 26
0
        /// <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 void ValidateSharedTableCompatibility(
            [NotNull] IReadOnlyList <IEntityType> mappedTypes, [NotNull] string tableName)
        {
            if (mappedTypes.Count == 1)
            {
                return;
            }

            var firstValidatedType = mappedTypes[0];
            var typesToValidate    = new Queue <IEntityType>();

            typesToValidate.Enqueue(firstValidatedType);
            var unvalidatedTypes = new HashSet <IEntityType>(mappedTypes.Skip(1));

            while (typesToValidate.Count > 0)
            {
                var entityType          = typesToValidate.Dequeue();
                var typesToValidateLeft = typesToValidate.Count;
                var nextTypeSet         = unvalidatedTypes.Where(
                    unvalidatedType =>
                    entityType.RootType() == unvalidatedType.RootType() ||
                    IsIdentifyingPrincipal(entityType, unvalidatedType) ||
                    IsIdentifyingPrincipal(unvalidatedType, entityType));
                foreach (var nextEntityType in nextTypeSet)
                {
                    var key      = entityType.FindPrimaryKey();
                    var otherKey = nextEntityType.FindPrimaryKey();
                    if (key.Relational().Name != otherKey.Relational().Name)
                    {
                        throw new InvalidOperationException(
                                  RelationalStrings.IncompatibleTableKeyNameMismatch(
                                      tableName,
                                      entityType.DisplayName(),
                                      nextEntityType.DisplayName(),
                                      key.Relational().Name,
                                      Property.Format(key.Properties),
                                      otherKey.Relational().Name,
                                      Property.Format(otherKey.Properties)));
                    }

                    typesToValidate.Enqueue(nextEntityType);
                }

                foreach (var typeToValidate in typesToValidate.Skip(typesToValidateLeft))
                {
                    unvalidatedTypes.Remove(typeToValidate);
                }
            }

            if (unvalidatedTypes.Count == 0)
            {
                return;
            }

            foreach (var invalidEntityType in unvalidatedTypes)
            {
                throw new InvalidOperationException(
                          RelationalStrings.IncompatibleTableNoRelationship(
                              tableName,
                              invalidEntityType.DisplayName(),
                              firstValidatedType.DisplayName(),
                              Property.Format(invalidEntityType.FindPrimaryKey().Properties),
                              Property.Format(firstValidatedType.FindPrimaryKey().Properties)));
            }
        }
Exemplo n.º 27
0
        protected override async Task ConsumeAsync(
            RelationalDataReader relationalReader, CancellationToken cancellationToken = default)
        {
            var commandPosition = 0;
            int rowsAffected;

            try
            {
                do
                {
                    while (commandPosition < CommandResultSet.Count &&
                           CommandResultSet[commandPosition] == ResultSetMapping.NoResultSet)
                    {
                        commandPosition++;
                    }

                    if (commandPosition < CommandResultSet.Count)
                    {
                        if (ModificationCommands[commandPosition].RequiresResultPropagation)
                        {
                            rowsAffected = 0;
                            do
                            {
                                var tableModification = ModificationCommands[commandPosition];
                                if (!await relationalReader.ReadAsync(cancellationToken))
                                {
                                    throw new DbUpdateConcurrencyException(
                                              RelationalStrings.UpdateConcurrencyException(
                                                  ModificationCommands.Count(m => m.RequiresResultPropagation), rowsAffected),
                                              ModificationCommands[commandPosition].Entries);
                                }

                                var valueBufferFactory = CreateValueBufferFactory(tableModification.ColumnModifications);
                                tableModification.PropagateResults(valueBufferFactory.Create(relationalReader.DbDataReader));
                                rowsAffected++;
                            }while (++commandPosition < CommandResultSet.Count &&
                                    CommandResultSet[commandPosition - 1] == ResultSetMapping.NotLastInResultSet);
                        }
                        else
                        {
                            var expectedRowsAffected = 1;
                            while (++commandPosition < CommandResultSet.Count &&
                                   CommandResultSet[commandPosition - 1] == ResultSetMapping.NotLastInResultSet)
                            {
                                expectedRowsAffected++;
                            }

                            if (relationalReader.Read())
                            {
                                rowsAffected = relationalReader.DbDataReader.GetInt32(0);
                                if (rowsAffected != expectedRowsAffected)
                                {
                                    throw new DbUpdateConcurrencyException(
                                              RelationalStrings.UpdateConcurrencyException(expectedRowsAffected, rowsAffected),
                                              ModificationCommands[commandPosition - 1].Entries);
                                }
                            }
                            else
                            {
                                throw new DbUpdateConcurrencyException(
                                          RelationalStrings.UpdateConcurrencyException(1, 0),
                                          ModificationCommands[commandPosition - 1].Entries);
                            }
                        }
                    }
                }while (commandPosition < CommandResultSet.Count &&
                        await relationalReader.DbDataReader.NextResultAsync(cancellationToken));
            }
            catch (DbUpdateException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new DbUpdateException(
                          RelationalStrings.UpdateStoreException,
                          ex, ModificationCommands[commandPosition].Entries);
            }
        }
Exemplo n.º 28
0
        public void Throws_for_unrecognized_types()
        {
            var ex = Assert.Throws <InvalidOperationException>(() => new SqlServerTypeMapper(new RelationalTypeMapperDependencies()).GetMapping("magic"));

            Assert.Equal(RelationalStrings.UnsupportedType("magic"), ex.Message);
        }
    protected override void Consume(RelationalDataReader reader)
    {
        var npgsqlReader = (NpgsqlDataReader)reader.DbDataReader;

#pragma warning disable 618
        Debug.Assert(npgsqlReader.Statements.Count == ModificationCommands.Count, $"Reader has {npgsqlReader.Statements.Count} statements, expected {ModificationCommands.Count}");
#pragma warning restore 618

        var commandIndex = 0;

        try
        {
            while (true)
            {
                // Find the next propagating command, if any
                int nextPropagating;
                for (nextPropagating = commandIndex;
                     nextPropagating < ModificationCommands.Count &&
                     !ModificationCommands[nextPropagating].RequiresResultPropagation;
                     nextPropagating++)
                {
                }

                // Go over all non-propagating commands before the next propagating one,
                // make sure they executed
                for (; commandIndex < nextPropagating; commandIndex++)
                {
#pragma warning disable 618
                    if (npgsqlReader.Statements[commandIndex].Rows == 0)
                    {
                        throw new DbUpdateConcurrencyException(
                                  RelationalStrings.UpdateConcurrencyException(1, 0),
                                  ModificationCommands[commandIndex].Entries
                                  );
                    }
#pragma warning restore 618
                }

                if (nextPropagating == ModificationCommands.Count)
                {
                    Debug.Assert(!npgsqlReader.NextResult(), "Expected less resultsets");
                    break;
                }

                // Propagate to results from the reader to the ModificationCommand

                var modificationCommand = ModificationCommands[commandIndex++];

                if (!reader.Read())
                {
                    throw new DbUpdateConcurrencyException(
                              RelationalStrings.UpdateConcurrencyException(1, 0),
                              modificationCommand.Entries);
                }

                var valueBufferFactory = CreateValueBufferFactory(modificationCommand.ColumnModifications);
                modificationCommand.PropagateResults(valueBufferFactory.Create(npgsqlReader));

                npgsqlReader.NextResult();
            }
        }
        catch (DbUpdateException)
        {
            throw;
        }
        catch (Exception ex)
        {
            throw new DbUpdateException(
                      RelationalStrings.UpdateStoreException,
                      ex,
                      ModificationCommands[commandIndex].Entries);
        }
    }
 public override async Task Include_collection_with_last_no_orderby(bool async)
 => Assert.Equal(
     RelationalStrings.LastUsedWithoutOrderBy(nameof(Enumerable.Last)),
     (await Assert.ThrowsAsync <InvalidOperationException>(
          () => base.Include_collection_with_last_no_orderby(async))).Message);