Reputation: 1216
public class ProcessInitialization
{
public Guid CorrelationId { get; set; }
public MyProcessContext ProcessContext { get; set; }
}
public class MyProcessContext
{
public int? ProcessId { get; set; }
}
Without using my convention I got
SELECT `process`.`CorrelationId`
FROM `ProcessInitialization` AS `process`
WHERE `process`.`ProcessContext_ProcessId` = 8
My convention makes snake_case
from PascalCase
:
public static void SetSimpleUnderscoreTableNameConvention(this ModelBuilder modelBuilder,
bool preserveAcronyms,
IDictionary<string, string> propertyMap = null,
IDictionary<string, string> entityMap = null
)
{
var propMap = propertyMap ?? new Dictionary<string, string>();
var entMap = entityMap ?? new Dictionary<string, string>();
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var prop in entity.GetProperties())
{
if (propMap.ContainsKey(prop.Name))
{
prop.Relational().ColumnName = propMap[prop.Name];
}
else
{
var underscoredProp = AddUndercoresToSentence(prop.Name, preserveAcronyms);
prop.Relational().ColumnName = underscoredProp.ToLowerInvariant();
}
}
var entName = entity.DisplayName();
if (entMap.ContainsKey(entName))
{
entity.Relational().TableName = entMap[entName];
}
else
{
var underscored = AddUndercoresToSentence(entity.DisplayName(), preserveAcronyms);
entity.Relational().TableName = underscored.ToLowerInvariant();
}
}
}
With it query becomes invalid:
SELECT `process`.`correlation_id`
FROM `process`
LEFT JOIN `process_initialization._process_context#_my_process_context` AS `process.ProcessContext` ON `process`.`correlation_id` = `process.ProcessContext`.`process_initialization_correlation_id`
WHERE `process.ProcessContext`.`process_id` = 8
Looks like I need to not apply my transformation to some of entity
:
var underscored = AddUndercoresToSentence(entity.DisplayName(), preserveAcronyms);
if (underscored.Contains("#")) // any other way to understand it is special?
continue;
entity.Relational().TableName = underscored.ToLowerInvariant();
After that I got:
The keys {'ProcessInitializationCorrelationId'} on 'ProcessInitialization.ProcessContext#MyProcessContext' and {'CorrelationId'} on 'ProcessInitialization' are both mapped to 'process_initialization.PK_process_initialization' but with different columns ({'process_initialization_correlation_id'} and {'correlation_id'}).
Upvotes: 1
Views: 480
Reputation: 205769
Owned types require special processing.
First, you recognize them by using IEntityType.IsOwned()
method.
Then, when the entity type is owned, you should skip the table name mapping (because they share the same table as the root owner entity). Also owned types have shadow PK properties which should be skipped, and for other properties you should build column name from the path from root owner to the owned type. The owner information is accessible through DefiningEntityType
and DefiningNavigationName
properties of IEntityType
.
Applying all that to your code:
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var prop in entity.GetProperties())
{
if (entity.IsOwned() && prop.IsPrimaryKey()) continue;
IEntityType propOwner = entity;
string propName = prop.Name, columnName = null;
do
{
if (!propMap.TryGetValue(propName, out var name))
name = AddUndercoresToSentence(propName, preserveAcronyms).ToLowerInvariant();
columnName = columnName == null ? name : name + "_" + columnName;
propName = propOwner.DefiningNavigationName;
propOwner = propOwner.DefiningEntityType;
}
while (propName != null);
prop.Relational().ColumnName = columnName;
}
if (entity.IsOwned()) continue;
var entName = entity.DisplayName();
if (!entMap.TryGetValue(entName, out var tableName))
tableName = AddUndercoresToSentence(entName, preserveAcronyms).ToLowerInvariant();
entity.Relational().TableName = tableName;
}
Upvotes: 2