Skip to content

Commit

Permalink
Remove common property prefix navigation naming (#29771)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers authored Dec 8, 2022
1 parent 241538c commit d67fa2b
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 25 deletions.
32 changes: 7 additions & 25 deletions src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,39 +104,21 @@ public virtual string GenerateCandidateIdentifier(string originalIdentifier)

private static string FindCandidateNavigationName(IEnumerable<IReadOnlyProperty> properties)
{
var count = properties.Count();
if (count == 0)
var name = "";
foreach (var property in properties)
{
return string.Empty;
}

var firstProperty = properties.First();
return StripId(
count == 1
? firstProperty.Name
: FindCommonPrefix(firstProperty.Name, properties.Select(p => p.Name)));
}

private static string FindCommonPrefix(string firstName, IEnumerable<string> propertyNames)
{
var prefixLength = 0;
foreach (var c in firstName)
{
foreach (var s in propertyNames)
if (name != "")
{
if (s.Length <= prefixLength
|| s[prefixLength] != c)
{
return firstName[..prefixLength];
}
return "";
}

prefixLength++;
name = property.Name;
}

return firstName[..prefixLength];
return StripId(name);
}


private static string StripId(string commonPrefix)
{
if (commonPrefix.Length < 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2600,4 +2600,231 @@ public void Composite_fk_property_ending_in_guid_navigation_name()
}
);
}

[ConditionalFact]
public void Unusual_navigation_name() // Issue #14278
{
var bookDetailsTable = new DatabaseTable
{
Database = Database,
Name = "Book_Details"
};

bookDetailsTable.Columns.Add(new DatabaseColumn
{
Table = bookDetailsTable,
Name = "ID",
StoreType = "int"
});

bookDetailsTable.Columns.Add(new DatabaseColumn
{
Table = bookDetailsTable,
Name = "Book_Name",
StoreType = "nvarchar(50)"
});

bookDetailsTable.Columns.Add(new DatabaseColumn
{
Table = bookDetailsTable,
Name = "Student_Id",
StoreType = "int"
});

bookDetailsTable.PrimaryKey = new DatabasePrimaryKey
{
Table = bookDetailsTable,
Name = "PK_Book_Details",
Columns = { bookDetailsTable.Columns.Single(c => c.Name == "ID") }
};

var studentDetailsTable = new DatabaseTable
{
Database = Database,
Name = "Student_Details"
};

studentDetailsTable.Columns.Add(new DatabaseColumn
{
Table = studentDetailsTable,
Name = "ID",
StoreType = "int"
});

studentDetailsTable.Columns.Add(new DatabaseColumn
{
Table = studentDetailsTable,
Name = "Student_Name",
StoreType = "nvarchar(256)"
});

studentDetailsTable.PrimaryKey = new DatabasePrimaryKey
{
Table = studentDetailsTable,
Name = "PK_Student_Details",
Columns = { studentDetailsTable.Columns.Single(c => c.Name == "ID") }
};

bookDetailsTable.ForeignKeys.Add(
new DatabaseForeignKey
{
Table = bookDetailsTable,
Name = "FK_Foo",
Columns = { bookDetailsTable.Columns.Single(c => c.Name == "Student_Id") },
PrincipalTable = studentDetailsTable,
PrincipalColumns = { studentDetailsTable.Columns.Single(c => c.Name == "ID") },
OnDelete = ReferentialAction.Cascade
});

var info = new DatabaseModel { Tables = { bookDetailsTable, studentDetailsTable } };

var model = _factory.Create(info, new ModelReverseEngineerOptions());

Assert.Collection(
model.GetEntityTypes().OrderBy(t => t.Name).Cast<EntityType>(),
entity =>
{
Assert.Equal("BookDetail", entity.Name);
Assert.Equal("Student", entity.GetNavigations().Single().Name);
},
entity =>
{
Assert.Equal("StudentDetail", entity.Name);
Assert.Equal("BookDetails", entity.GetNavigations().Single().Name);
}
);

model = _factory.Create(info, new ModelReverseEngineerOptions { UseDatabaseNames = true });

Assert.Collection(
model.GetEntityTypes().OrderBy(t => t.Name).Cast<EntityType>(),
entity =>
{
Assert.Equal("Book_Detail", entity.Name);
Assert.Equal("Student", entity.GetNavigations().Single().Name);
},
entity =>
{
Assert.Equal("Student_Detail", entity.Name);
Assert.Equal("Book_Details", entity.GetNavigations().Single().Name);
}
);
}

[ConditionalFact]
public void Interesting_navigation_name() // Issue #27832
{
var seasonTable = new DatabaseTable { Database = Database, Name = "TmTvSeason" };

seasonTable.Columns.Add(
new DatabaseColumn
{
Table = seasonTable,
Name = "Id",
StoreType = "int"
});

seasonTable.Columns.Add(
new DatabaseColumn
{
Table = seasonTable,
Name = "ShowId",
StoreType = "int"
});

seasonTable.Columns.Add(
new DatabaseColumn
{
Table = seasonTable,
Name = "Name",
StoreType = "nvarchar(300)"
});

seasonTable.PrimaryKey = new DatabasePrimaryKey
{
Table = seasonTable,
Name = "PK_TmTvSeason",
Columns = { seasonTable.Columns.Single(c => c.Name == "ShowId"), seasonTable.Columns.Single(c => c.Name == "Id") }
};

var episodeTable = new DatabaseTable { Database = Database, Name = "TmTvEpisode" };

episodeTable.Columns.Add(
new DatabaseColumn
{
Table = episodeTable,
Name = "Id",
StoreType = "int"
});

episodeTable.Columns.Add(
new DatabaseColumn
{
Table = episodeTable,
Name = "SeasonId",
StoreType = "int"
});

episodeTable.Columns.Add(
new DatabaseColumn
{
Table = episodeTable,
Name = "ShowId",
StoreType = "int"
});

episodeTable.Columns.Add(
new DatabaseColumn
{
Table = episodeTable,
Name = "Name",
StoreType = "nvarchar(300)"
});

episodeTable.PrimaryKey = new DatabasePrimaryKey
{
Table = episodeTable,
Name = "PK_TmTvEpisode",
Columns =
{
episodeTable.Columns.Single(c => c.Name == "ShowId"),
episodeTable.Columns.Single(c => c.Name == "SeasonId"),
episodeTable.Columns.Single(c => c.Name == "Id")
}
};

episodeTable.ForeignKeys.Add(
new DatabaseForeignKey
{
Table = episodeTable,
Name = "FK_TmTvEpisode_TmTvSeason",
Columns = { episodeTable.Columns.Single(c => c.Name == "ShowId"), episodeTable.Columns.Single(c => c.Name == "SeasonId") },
PrincipalTable = seasonTable,
PrincipalColumns = { seasonTable.Columns.Single(c => c.Name == "ShowId"), seasonTable.Columns.Single(c => c.Name == "Id") },
OnDelete = ReferentialAction.Cascade
});

var info = new DatabaseModel { Tables = { seasonTable, episodeTable } };

var model = _factory.Create(info, new ModelReverseEngineerOptions());
AssertNavigations();

model = _factory.Create(info, new ModelReverseEngineerOptions { UseDatabaseNames = true });
AssertNavigations();

void AssertNavigations()
=> Assert.Collection(
model.GetEntityTypes().OrderBy(t => t.Name).Cast<EntityType>(),
entity =>
{
Assert.Equal("TmTvEpisode", entity.Name);
Assert.Equal("TmTvSeason", entity.GetNavigations().Single().Name);
},
entity =>
{
Assert.Equal("TmTvSeason", entity.Name);
Assert.Equal("TmTvEpisodes", entity.GetNavigations().Single().Name);
}
);
}
}

0 comments on commit d67fa2b

Please sign in to comment.