Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RevEng: Don't produce HasIndex() API if it would already be assumed #4039

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,40 @@ public class KeyFluentApiConfiguration : IFluentApiConfiguration
{
public KeyFluentApiConfiguration(
[NotNull] string lambdaIdentifier,
[NotNull] IReadOnlyList<Property> properties)
[NotNull] Key key)
{
Check.NotEmpty(lambdaIdentifier, nameof(lambdaIdentifier));
Check.NotEmpty(properties, nameof(properties));
Check.NotNull(key, nameof(key));

LambdaIdentifier = lambdaIdentifier;
Properties = new List<Property>(properties);
Key = key;
}

public virtual string LambdaIdentifier { get; }
public virtual IReadOnlyList<Property> Properties { get; }
public virtual Key Key { get; }

public virtual bool HasAttributeEquivalent { get; set; }

public virtual ICollection<string> FluentApiLines =>
new List<string> { string.Format(
CultureInfo.InvariantCulture,
"{0}({1} => {2})",
nameof(EntityTypeBuilder.HasKey),
LambdaIdentifier,
new ScaffoldingUtilities().GenerateLambdaToKey(Properties, LambdaIdentifier))
};
public virtual ICollection<string> FluentApiLines
{
get
{
var lines = new List<string>();
lines.Add(string.Format(
CultureInfo.InvariantCulture,
"{0}({1} => {2})",
nameof(EntityTypeBuilder.HasKey),
LambdaIdentifier,
new ScaffoldingUtilities().GenerateLambdaToKey(Key.Properties, LambdaIdentifier)));

if (Key.Relational().Name != null)
{
lines.Add("." + nameof(RelationalKeyBuilderExtensions.HasName)
+ "(" + CSharpUtilities.Instance.DelimitString(Key.Relational().Name) + ")");
}

return lines;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,15 @@ public virtual void AddKeyConfiguration([NotNull] EntityConfiguration entityConf
if (key.IsPrimaryKey())
{
var keyFluentApi = _configurationFactory
.CreateKeyFluentApiConfiguration("e", key.Properties);

if (key.Properties.Count == 1)
.CreateKeyFluentApiConfiguration("e", key);

if (key.Properties.Count == 1
&& key.Relational().Name ==
RelationalKeyAnnotations
.GetDefaultKeyName(
entityType.Relational().TableName,
true, /* is primary key */
key.Properties.Select(p => p.Name)))
{
keyFluentApi.HasAttributeEquivalent = true;

Expand Down Expand Up @@ -241,15 +247,9 @@ public virtual void AddIndexConfigurations([NotNull] EntityConfiguration entityC
{
Check.NotNull(entityConfiguration, nameof(entityConfiguration));

var entityType = (EntityType)entityConfiguration.EntityType;
var primaryKeyProperties = entityType.FindPrimaryKey()?.Properties;
foreach (var index in entityType.GetIndexes())
foreach (var index in entityConfiguration.EntityType.GetIndexes().Cast<Index>())
{
// do not add indexes for the primary key
if (!index.Properties.SequenceEqual(primaryKeyProperties))
{
AddIndexConfiguration(entityConfiguration, index);
}
AddIndexConfiguration(entityConfiguration, index);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,12 @@ public virtual FluentApiConfiguration CreateFluentApiConfiguration(

public virtual KeyFluentApiConfiguration CreateKeyFluentApiConfiguration(
[NotNull] string lambdaIdentifier,
[NotNull] IReadOnlyList<Property> properties)
[NotNull] Key key)
{
Check.NotEmpty(lambdaIdentifier, nameof(lambdaIdentifier));
Check.NotEmpty(properties, nameof(properties));
Check.NotNull(key, nameof(key));

return new KeyFluentApiConfiguration(lambdaIdentifier, properties);
return new KeyFluentApiConfiguration(lambdaIdentifier, key);
}

public virtual AttributeConfiguration CreateAttributeConfiguration(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using JetBrains.Annotations;
using Microsoft.Data.Entity.Internal;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Metadata.Builders;
using Microsoft.Data.Entity.Metadata.Internal;
using Microsoft.Data.Entity.Scaffolding.Internal.Configuration;
using Microsoft.Data.Entity.Utilities;
Expand Down Expand Up @@ -52,7 +53,7 @@ public virtual void LayoutRelationshipConfigurationLines(
Check.NotEmpty(principalEndLambdaIdentifier, nameof(principalEndLambdaIdentifier));

sb.Append(entityLambdaIdentifier);
sb.Append(".HasOne(");
sb.Append("." + nameof(EntityTypeBuilder<EntityType>.HasOne) + "(");
sb.Append(dependentEndLambdaIdentifier);
sb.Append(" => ");
sb.Append(dependentEndLambdaIdentifier);
Expand All @@ -62,14 +63,10 @@ public virtual void LayoutRelationshipConfigurationLines(

using (sb.Indent())
{
if (rc.ForeignKey.IsUnique)
{
sb.Append(".WithOne(");
}
else
{
sb.Append(".WithMany(");
}
var withMethodName = rc.ForeignKey.IsUnique
? nameof(ReferenceNavigationBuilder<EntityType, EntityType>.WithOne)
: nameof(ReferenceNavigationBuilder<EntityType, EntityType>.WithMany);
sb.Append("." + withMethodName + "(");
if (!string.IsNullOrEmpty(rc.PrincipalEndNavigationPropertyName))
{
sb.Append(principalEndLambdaIdentifier);
Expand All @@ -82,7 +79,10 @@ public virtual void LayoutRelationshipConfigurationLines(

if (!rc.ForeignKey.PrincipalKey.IsPrimaryKey())
{
sb.Append(".HasPrincipalKey");
var hasPrincipalKeyMethodName = rc.ForeignKey.IsUnique
? nameof(ReferenceReferenceBuilder<EntityType, EntityType>.HasPrincipalKey)
: nameof(ReferenceReferenceBuilder.HasPrincipalKey);
sb.Append("." + hasPrincipalKeyMethodName);
if (rc.ForeignKey.IsUnique)
{
// If the relationship is 1:1 need to define to which end
Expand All @@ -98,7 +98,10 @@ public virtual void LayoutRelationshipConfigurationLines(
.AppendLine(")");
}

sb.Append(".HasForeignKey");
var hasForeignKeyMethodName = rc.ForeignKey.IsUnique
? nameof(ReferenceReferenceBuilder<EntityType, EntityType>.HasForeignKey)
: nameof(ReferenceCollectionBuilder.HasForeignKey);
sb.Append("." + hasForeignKeyMethodName);
if (rc.ForeignKey.IsUnique)
{
// If the relationship is 1:1 need to define to which end
Expand All @@ -121,11 +124,31 @@ public virtual void LayoutRelationshipConfigurationLines(
if (rc.OnDeleteAction != defaultOnDeleteAction)
{
sb.AppendLine();
sb.Append(".OnDelete(");
var onDeleteMethodName = rc.ForeignKey.IsUnique
? nameof(ReferenceReferenceBuilder.OnDelete)
: nameof(ReferenceCollectionBuilder.OnDelete);
sb.Append("." + onDeleteMethodName + "(");
sb.Append(CSharpUtilities.Instance.GenerateLiteral(rc.OnDeleteAction));
sb.Append(")");
}

var foreignKey = rc.ForeignKey as ForeignKey;
if (foreignKey != null
&& foreignKey.Relational().Name !=
RelationalForeignKeyAnnotations.GetDefaultForeignKeyName(
foreignKey.DeclaringEntityType.Relational().TableName,
foreignKey.PrincipalEntityType.Relational().TableName,
foreignKey.Properties.Select(p => p.Name)))
{
sb.AppendLine();
var hasConstraintMethodName = foreignKey.IsUnique
? nameof(RelationalReferenceReferenceBuilderExtensions.HasConstraintName)
: nameof(RelationalReferenceCollectionBuilderExtensions.HasConstraintName);
sb.Append("." + hasConstraintMethodName + "(");
sb.Append(CSharpUtilities.Instance.DelimitString(foreignKey.Relational().Name));
sb.Append(")");
}

sb.AppendLine(";");
}
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@
<data name="DataTypeDoesNotAllowSqlServerIdentityStrategy" xml:space="preserve">
<value>For column {columnId}. This column is set up as an Identity column, but the SQL Server data type is {sqlServerDataType}. This will be mapped to CLR type byte which does not allow the SqlServerValueGenerationStrategy.IdentityColumn setting. Generating a matching Property but ignoring the Identity setting.</value>
</data>
<data name="ForeignKeyNameEmpty" xml:space="preserve">
<value>Found a foreign key on table [{schemaName}].[{tableName}] with an empty or null name. Skipping foreign key.</value>
</data>
<data name="IndexNameEmpty" xml:space="preserve">
<value>Found an index on table [{schemaName}].[{tableName}] with an empty or null name. Skipping index.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ FROM sys.indexes i
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND c.column_id = ic.column_id
WHERE object_schema_name(i.object_id) <> 'sys'
AND i.is_primary_key <> 1
AND object_name(i.object_id) <> '" + HistoryRepository.DefaultTableName + @"'
ORDER BY object_schema_name(i.object_id), object_name(i.object_id), i.name, ic.key_ordinal";

Expand Down Expand Up @@ -321,6 +320,7 @@ FROM sys.foreign_keys AS f
var fkName = reader.GetStringOrNull(2);
if (string.IsNullOrEmpty(fkName))
{
Logger.LogWarning(SqlServerDesignStrings.ForeignKeyNameEmpty(schemaName, tableName));
continue;
}

Expand Down Expand Up @@ -349,6 +349,7 @@ FROM sys.foreign_keys AS f

fkInfo = new ForeignKeyModel
{
Name = fkName,
Table = table,
PrincipalTable = principalTable
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ protected virtual KeyBuilder VisitPrimaryKey([NotNull] EntityTypeBuilder builder
.Where(c => c.PrimaryKeyOrdinal.HasValue)
.OrderBy(c => c.PrimaryKeyOrdinal)
.ToList();

if (keyColumns.Count == 0)
{
Logger.LogWarning(RelationalDesignStrings.MissingPrimaryKey(table.DisplayName));
Expand Down Expand Up @@ -274,15 +274,40 @@ protected virtual IndexBuilder VisitIndex([NotNull] EntityTypeBuilder builder, [
Check.NotNull(builder, nameof(builder));
Check.NotNull(index, nameof(index));

var properties = index.Columns.Select(GetPropertyName).ToArray();
var propertyNames = index.Columns.Select(GetPropertyName).ToArray();

if (properties.Count(p => builder.Metadata.FindProperty(p) != null) != properties.Length)
if (propertyNames.Count(p => builder.Metadata.FindProperty(p) != null) != propertyNames.Length)
{
Logger.LogWarning(RelationalDesignStrings.UnableToScaffoldIndexMissingProperty(index.Name));
return null;
}

var indexBuilder = builder.HasIndex(properties)
var columnNames = index.Columns.Select(c => c.Name);
if (index.Table != null)
{
var primaryKeyColumns = index.Table.Columns
.Where(c => c.PrimaryKeyOrdinal.HasValue)
.OrderBy(c => c.PrimaryKeyOrdinal);
if (columnNames.SequenceEqual(primaryKeyColumns.Select(c => c.Name)))
{
// index is supporting the primary key. So there is no need for
// an extra index in the model. But if the index name does not
// match what would be produced by default then need to call
// HasName() on the primary key.
if (index.Name !=
RelationalKeyAnnotations
.GetDefaultKeyName(
index.Table.Name,
true, /* is primary key */
primaryKeyColumns.Select(c => GetPropertyName(c))))
{
builder.HasKey(propertyNames.ToArray()).HasName(index.Name);
}
return null;
}
}

var indexBuilder = builder.HasIndex(propertyNames)
.IsUnique(index.IsUnique);

if (!string.IsNullOrEmpty(index.Name))
Expand All @@ -292,7 +317,7 @@ protected virtual IndexBuilder VisitIndex([NotNull] EntityTypeBuilder builder, [

if (index.IsUnique)
{
var keyBuilder = builder.HasAlternateKey(properties);
var keyBuilder = builder.HasAlternateKey(propertyNames);
if (!string.IsNullOrEmpty(index.Name))
{
keyBuilder.HasName(index.Name);
Expand Down Expand Up @@ -389,6 +414,8 @@ protected virtual IMutableForeignKey VisitForeignKey([NotNull] ModelBuilder mode

key.IsUnique = dependentEntityType.FindKey(depProps) != null;

key.Relational().Name = foreignKey.Name;

AssignOnDeleteAction(foreignKey, key);

return key;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Metadata.Internal;
Expand Down Expand Up @@ -40,9 +41,22 @@ protected virtual string GetDefaultName()
ForeignKey.PrincipalEntityType,
Annotations.ProviderPrefix);

return "FK_" + entityType.TableName +
"_" + principalEntityType.TableName +
"_" + string.Join("_", ForeignKey.Properties.Select(p => p.Name));
return GetDefaultForeignKeyName(entityType.TableName,
principalEntityType.TableName, ForeignKey.Properties.Select(p => p.Name));
}

public static string GetDefaultForeignKeyName(
[NotNull] string dependentTableName,
[NotNull] string principalTableName,
[NotNull] IEnumerable<string> dependentEndPropertyNames)
{
Check.NotEmpty(dependentTableName, nameof(dependentTableName));
Check.NotEmpty(principalTableName, nameof(principalTableName));
Check.NotNull(dependentEndPropertyNames, nameof(dependentEndPropertyNames));

return "FK_" + dependentTableName +
"_" + principalTableName +
"_" + string.Join("_", dependentEndPropertyNames);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
Expand Down Expand Up @@ -36,18 +37,27 @@ protected virtual bool SetName([CanBeNull] string value)

protected virtual string GetDefaultName()
{
var builder = new StringBuilder();
var entityType = new RelationalEntityTypeAnnotations(Key.DeclaringEntityType, Annotations.ProviderPrefix);

return GetDefaultKeyName(entityType.TableName, Key.IsPrimaryKey(), Key.Properties.Select(p => p.Name));
}

public static string GetDefaultKeyName(
[NotNull] string tableName, bool primaryKey, [NotNull] IEnumerable<string> propertyNames)
{
Check.NotEmpty(tableName, nameof(tableName));
Check.NotNull(propertyNames, nameof(propertyNames));

var builder = new StringBuilder();
builder
.Append(Key.IsPrimaryKey() ? "PK_" : "AK_")
.Append(entityType.TableName);
.Append(primaryKey ? "PK_" : "AK_")
.Append(tableName);

if (!Key.IsPrimaryKey())
if (!primaryKey)
{
builder
.Append("_")
.Append(string.Join("_", Key.Properties.Select(p => p.Name)));
.Append(string.Join("_", propertyNames));
}

return builder.ToString();
Expand Down
Loading