Skip to content

Commit 8d65369

Browse files
authored
Merge pull request #303 from phofman/Feature/navprop_attrs
Defining custom annotations to each Navigation Property separately
2 parents 3f263a2 + 4e3ff9c commit 8d65369

File tree

3 files changed

+61
-28
lines changed

3 files changed

+61
-28
lines changed

EntityFramework.Reverse.POCO.Generator/Database.tt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,21 @@
458458
return fkName;
459459
};
460460

461+
/*
462+
ForeignKeyAnnotationsProcessing = (Table fkTable, Table pkTable, string propName) =>
463+
{
464+
// each navigation property that is a reference to User are left intact
465+
if (pkTable.NameHumanCase.Equals("User"))
466+
{
467+
if (propName.Equals("User"))
468+
return null;
469+
}
470+
471+
// all the others are marked with this attribute
472+
return new[] { "System.Runtime.Serialization.IgnoreDataMember" };
473+
};
474+
*/
475+
461476
// Return true to include this table in the db context
462477
ConfigurationFilter = (Table t) =>
463478
{

EntityFramework.Reverse.POCO.Generator/EF.Reverse.POCO.Core.ttinclude

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
static Func<string, StoredProcedure, string> StoredProcedureReturnModelRename;
9494
Func<Column, Table, Column> UpdateColumn;
9595
Func<IList<ForeignKey>, Table, Table, bool, ForeignKey> ForeignKeyProcessing;
96+
Func<Table, Table, string, string[]> ForeignKeyAnnotationsProcessing;
9697
Func<ForeignKey, ForeignKey> ForeignKeyFilter;
9798
Func<string, ForeignKey, string, Relationship, short, string> ForeignKeyName;
9899
string MigrationConfigurationFileName = null;
@@ -638,17 +639,17 @@
638639
}
639640

640641
// Work out if there are any foreign key relationship naming clashes
641-
reader.ProcessForeignKeys(fkList, tables, UsePascalCase, PrependSchemaName, CollectionType, true, IncludeComments, ForeignKeyName, UseDataAnnotationsSchema, ForeignKeyProcessing);
642+
reader.ProcessForeignKeys(fkList, tables, UsePascalCase, PrependSchemaName, CollectionType, true, IncludeComments, ForeignKeyName, UseDataAnnotationsSchema, ForeignKeyProcessing, ForeignKeyAnnotationsProcessing);
642643
if(UseMappingTables)
643-
tables.IdentifyMappingTables(fkList, UsePascalCase, CollectionType, true, IncludeComments, IsSqlCe, ForeignKeyName);
644+
tables.IdentifyMappingTables(fkList, UsePascalCase, CollectionType, true, IncludeComments, IsSqlCe, ForeignKeyName, ForeignKeyAnnotationsProcessing);
644645

645646
// Now we know our foreign key relationships and have worked out if there are any name clashes,
646647
// re-map again with intelligently named relationships.
647648
tables.ResetNavigationProperties();
648649

649-
reader.ProcessForeignKeys(fkList, tables, UsePascalCase, PrependSchemaName, CollectionType, false, IncludeComments, ForeignKeyName, UseDataAnnotationsSchema, ForeignKeyProcessing);
650+
reader.ProcessForeignKeys(fkList, tables, UsePascalCase, PrependSchemaName, CollectionType, false, IncludeComments, ForeignKeyName, UseDataAnnotationsSchema, ForeignKeyProcessing, ForeignKeyAnnotationsProcessing);
650651
if(UseMappingTables)
651-
tables.IdentifyMappingTables(fkList, UsePascalCase, CollectionType, false, IncludeComments, IsSqlCe, ForeignKeyName);
652+
tables.IdentifyMappingTables(fkList, UsePascalCase, CollectionType, false, IncludeComments, IsSqlCe, ForeignKeyName, ForeignKeyAnnotationsProcessing);
652653

653654
conn.Close();
654655
return tables;
@@ -805,6 +806,7 @@
805806
{
806807
public string Definition;
807808
public string Comments;
809+
public string[] AdditionalDataAnnotations;
808810
}
809811

810812
public class Column
@@ -1499,7 +1501,7 @@
14991501
public abstract Tables ReadSchema(Regex schemaFilterExclude, Regex schemaFilterInclude, Regex tableFilterExclude, Regex tableFilterInclude, Regex columnFilterExclude, Func<Table, bool> tableFilter, bool usePascalCase, bool prependSchemaName, CommentsStyle includeComments, bool includeViews, CommentsStyle includeExtendedPropertyComments, Func<string, string, bool, string> tableRename, Func<Column, Table, Column> updateColumn, bool usePrivateSetterForComputedColumns, bool includeSynonyms, bool dataAnnotations, bool dataAnnotationsSchema, bool isSqlCe, Dictionary<string, string> columnNameToDataAnnotation, bool includeConnectionSettingComments);
15001502
public abstract List<StoredProcedure> ReadStoredProcs(Regex SchemaFilterExclude, Regex storedProcedureFilterExclude, bool usePascalCase, bool prependSchemaName , Func<StoredProcedure, string> StoredProcedureRename, bool includeTableValuedFunctions, bool includeConnectionSettingComments);
15011503
public abstract List<ForeignKey> ReadForeignKeys(Func<string, string, bool, string> tableRename, Func<ForeignKey, ForeignKey> foreignKeyFilter);
1502-
public abstract void ProcessForeignKeys(List<ForeignKey> fkList, Tables tables, bool usePascalCase, bool prependSchemaName, string collectionType, bool checkForFkNameClashes, CommentsStyle includeComments, Func<string, ForeignKey, string, Relationship, short, string> ForeignKeyName, bool dataAnnotationsSchema, Func<IList<ForeignKey>, Table, Table, bool, ForeignKey> foreignKeyProcessing);
1504+
public abstract void ProcessForeignKeys(List<ForeignKey> fkList, Tables tables, bool usePascalCase, bool prependSchemaName, string collectionType, bool checkForFkNameClashes, CommentsStyle includeComments, Func<string, ForeignKey, string, Relationship, short, string> ForeignKeyName, bool dataAnnotationsSchema, Func<IList<ForeignKey>, Table, Table, bool, ForeignKey> foreignKeyProcessing, Func<Table, Table, string, string[]> foreignKeyAnnotationsProcessing);
15031505
public abstract void IdentifyForeignKeys(List<ForeignKey> fkList, Tables tables);
15041506
public abstract void ReadIndexes(Tables tables);
15051507
public abstract void ReadExtendedProperties(Tables tables, bool includeConnectionSettingComments);
@@ -2607,7 +2609,7 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
26072609
}
26082610
}
26092611

2610-
public override void ProcessForeignKeys(List<ForeignKey> fkList, Tables tables, bool usePascalCase, bool prependSchemaName, string collectionType, bool checkForFkNameClashes, CommentsStyle includeComments, Func<string, ForeignKey, string, Relationship, short, string> ForeignKeyName, bool dataAnnotationsSchema, Func<IList<ForeignKey>, Table, Table, bool, ForeignKey> foreignKeyProcessing)
2612+
public override void ProcessForeignKeys(List<ForeignKey> fkList, Tables tables, bool usePascalCase, bool prependSchemaName, string collectionType, bool checkForFkNameClashes, CommentsStyle includeComments, Func<string, ForeignKey, string, Relationship, short, string> ForeignKeyName, bool dataAnnotationsSchema, Func<IList<ForeignKey>, Table, Table, bool, ForeignKey> foreignKeyProcessing, Func<Table, Table, string, string[]> foreignKeyAnnotationsProcessing)
26112613
{
26122614
var constraints = fkList.Select(x => x.FkSchema + "." + x.ConstraintName).Distinct();
26132615
foreach (var constraint in constraints)
@@ -2670,6 +2672,7 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
26702672
}
26712673

26722674
var fkd = new PropertyAndComments();
2675+
fkd.AdditionalDataAnnotations = foreignKeyAnnotationsProcessing != null ? foreignKeyAnnotationsProcessing(fkTable, pkTable, pkPropName) : null;
26732676
fkd.Definition = string.Format("{0}public {1}{2} {3} {4}{5}", dataAnnotation, Table.GetLazyLoadingMarker(), pkTableHumanCaseWithSuffix, pkPropName, "{ get; set; }", includeComments != CommentsStyle.None ? " // " + foreignKey.ConstraintName : string.Empty);
26742677
fkd.Comments = string.Format("Parent {0} pointed by [{1}].({2}) ({3})", pkTableHumanCase, fkTable.Name, string.Join(", ", fkCols.Select(x => "[" + x.col.NameHumanCase + "]").Distinct().ToArray()), foreignKey.ConstraintName);
26752678
fkCol.col.EntityFk.Add(fkd);
@@ -2691,7 +2694,7 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
26912694
}
26922695

26932696
if(foreignKey.IncludeReverseNavigation)
2694-
pkTable.AddReverseNavigation(relationship, pkTableHumanCase, fkTable, fkPropName, string.Format("{0}.{1}", fkTable.Name, foreignKey.ConstraintName), collectionType, includeComments, foreignKeys);
2697+
pkTable.AddReverseNavigation(relationship, pkTableHumanCase, fkTable, fkPropName, string.Format("{0}.{1}", fkTable.Name, foreignKey.ConstraintName), collectionType, includeComments, foreignKeys, foreignKeyAnnotationsProcessing);
26952698
}
26962699
}
26972700

@@ -3317,7 +3320,7 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
33173320
return ForeignKeyName(tableNameHumanCase, foreignKey, fkName, relationship, 6);
33183321
}
33193322

3320-
public void AddReverseNavigation(Relationship relationship, string fkName, Table fkTable, string propName, string constraint, string collectionType, CommentsStyle includeComments, List<ForeignKey> fks, Table mappingTable = null)
3323+
public void AddReverseNavigation(Relationship relationship, string fkName, Table fkTable, string propName, string constraint, string collectionType, CommentsStyle includeComments, List<ForeignKey> fks, Func<Table, Table, string, string[]> foreignKeyAnnotationsProcessing = null, Table mappingTable = null)
33213324
{
33223325
string fkNames = "";
33233326
switch (relationship)
@@ -3339,6 +3342,7 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
33393342
ReverseNavigationProperty.Add(
33403343
new PropertyAndComments()
33413344
{
3345+
AdditionalDataAnnotations = foreignKeyAnnotationsProcessing != null ? foreignKeyAnnotationsProcessing(fkTable, this, propName) : null,
33423346
Definition = string.Format("public {0}{1} {2} {{ get; set; }}{3}", GetLazyLoadingMarker(), fkTable.NameHumanCaseWithSuffix, propName, includeComments != CommentsStyle.None ? " // " + constraint : string.Empty),
33433347
Comments = string.Format("Parent (One-to-One) {0} pointed by [{1}].{2} ({3})", this.NameHumanCaseWithSuffix, fkTable.Name, fkNames, fks.First().ConstraintName)
33443348
}
@@ -3349,6 +3353,7 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
33493353
ReverseNavigationProperty.Add(
33503354
new PropertyAndComments()
33513355
{
3356+
AdditionalDataAnnotations = foreignKeyAnnotationsProcessing != null ? foreignKeyAnnotationsProcessing(fkTable, this, propName) : null,
33523357
Definition = string.Format("public {0}{1} {2} {{ get; set; }}{3}", GetLazyLoadingMarker(), fkTable.NameHumanCaseWithSuffix, propName, includeComments != CommentsStyle.None ? " // " + constraint : string.Empty),
33533358
Comments = string.Format("Parent {0} pointed by [{1}].{2} ({3})", NameHumanCaseWithSuffix, fkTable.Name, fkNames, fks.First().ConstraintName)
33543359
}
@@ -3362,6 +3367,7 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
33623367
ReverseNavigationProperty.Add(
33633368
new PropertyAndComments()
33643369
{
3370+
AdditionalDataAnnotations = foreignKeyAnnotationsProcessing != null ? foreignKeyAnnotationsProcessing(fkTable, this, propName) : null,
33653371
Definition = string.Format("public {0}System.Collections.Generic.ICollection<{1}> {2} {{ get; set; }}{3}{4}", GetLazyLoadingMarker(), fkTable.NameHumanCaseWithSuffix, propName, initialization1, includeComments != CommentsStyle.None ? " // " + constraint : string.Empty),
33663372
Comments = string.Format("Child {0} where [{1}].{2} point to this entity ({3})", Inflector.MakePlural(fkTable.NameHumanCase), fkTable.Name, fkNames, fks.First().ConstraintName)
33673373
}
@@ -3376,6 +3382,7 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
33763382
ReverseNavigationProperty.Add(
33773383
new PropertyAndComments()
33783384
{
3385+
AdditionalDataAnnotations = foreignKeyAnnotationsProcessing != null ? foreignKeyAnnotationsProcessing(fkTable, this, propName) : null,
33793386
Definition = string.Format("public {0}System.Collections.Generic.ICollection<{1}> {2} {{ get; set; }}{3}{4}", GetLazyLoadingMarker(), fkTable.NameHumanCaseWithSuffix, propName, initialization2, includeComments != CommentsStyle.None ? " // Many to many mapping" : string.Empty),
33803387
Comments = string.Format("Child {0} (Many-to-Many) mapped by table [{1}]", Inflector.MakePlural(fkTable.NameHumanCase), mappingTable == null ? string.Empty : mappingTable.Name)
33813388
}
@@ -3399,7 +3406,7 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
33993406
}});", leftPropName, rightPropName, left.FkTableName, left.FkColumn, right.FkColumn, isSqlCe ? string.Empty : ", \"" + left.FkSchema + "\""));
34003407
}
34013408

3402-
public void IdentifyMappingTable(List<ForeignKey> fkList, Tables tables, bool usePascalCase, string collectionType, bool checkForFkNameClashes, CommentsStyle includeComments, bool isSqlCe, Func<string, ForeignKey, string, Relationship, short, string> ForeignKeyName)
3409+
public void IdentifyMappingTable(List<ForeignKey> fkList, Tables tables, bool usePascalCase, string collectionType, bool checkForFkNameClashes, CommentsStyle includeComments, bool isSqlCe, Func<string, ForeignKey, string, Relationship, short, string> foreignKeyName, Func<Table, Table, string, string[]> foreignKeyAnnotationsProcessing)
34033410
{
34043411
IsMapping = false;
34053412

@@ -3440,13 +3447,13 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
34403447
if (rightTable == null)
34413448
return;
34423449

3443-
var leftPropName = leftTable.GetUniqueColumnName(rightTable.NameHumanCase, right, usePascalCase, checkForFkNameClashes, false, ForeignKeyName, Relationship.ManyToOne); // relationship from the mapping table to each side is Many-to-One
3444-
var rightPropName = rightTable.GetUniqueColumnName(leftTable.NameHumanCase, left, usePascalCase, checkForFkNameClashes, false, ForeignKeyName, Relationship.ManyToOne); // relationship from the mapping table to each side is Many-to-One
3450+
var leftPropName = leftTable.GetUniqueColumnName(rightTable.NameHumanCase, right, usePascalCase, checkForFkNameClashes, false, foreignKeyName, Relationship.ManyToOne); // relationship from the mapping table to each side is Many-to-One
3451+
var rightPropName = rightTable.GetUniqueColumnName(leftTable.NameHumanCase, left, usePascalCase, checkForFkNameClashes, false, foreignKeyName, Relationship.ManyToOne); // relationship from the mapping table to each side is Many-to-One
34453452
leftTable.AddMappingConfiguration(left, right, usePascalCase, leftPropName, rightPropName, isSqlCe);
34463453

34473454
IsMapping = true;
3448-
rightTable.AddReverseNavigation(Relationship.ManyToMany, rightTable.NameHumanCase, leftTable, rightPropName, null, collectionType, includeComments, null, mappingTable: this);
3449-
leftTable .AddReverseNavigation(Relationship.ManyToMany, leftTable.NameHumanCase, rightTable, leftPropName, null, collectionType, includeComments, null, mappingTable: this);
3455+
rightTable.AddReverseNavigation(Relationship.ManyToMany, rightTable.NameHumanCase, leftTable, rightPropName, null, collectionType, includeComments, null, foreignKeyAnnotationsProcessing, this);
3456+
leftTable.AddReverseNavigation(Relationship.ManyToMany, leftTable.NameHumanCase, rightTable, leftPropName, null, collectionType, includeComments, null, foreignKeyAnnotationsProcessing, this);
34503457
}
34513458

34523459
public void SetupDataAnnotations()
@@ -3478,11 +3485,11 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
34783485
}
34793486
}
34803487

3481-
public void IdentifyMappingTables(List<ForeignKey> fkList, bool usePascalCase, string collectionType, bool checkForFkNameClashes, CommentsStyle includeComments, bool isSqlCe, Func<string, ForeignKey, string, Relationship, short, string> ForeignKeyName)
3488+
public void IdentifyMappingTables(List<ForeignKey> fkList, bool usePascalCase, string collectionType, bool checkForFkNameClashes, CommentsStyle includeComments, bool isSqlCe, Func<string, ForeignKey, string, Relationship, short, string> foreignKeyName, Func<Table, Table, string, string[]> foreignKeyAnnotationsProcessing)
34823489
{
34833490
foreach(var tbl in this.Where(x => x.HasForeignKey))
34843491
{
3485-
tbl.IdentifyMappingTable(fkList, this, usePascalCase, collectionType, checkForFkNameClashes, includeComments, isSqlCe, ForeignKeyName);
3492+
tbl.IdentifyMappingTable(fkList, this, usePascalCase, collectionType, checkForFkNameClashes, includeComments, isSqlCe, foreignKeyName, foreignKeyAnnotationsProcessing);
34863493
}
34873494
}
34883495

EntityFramework.Reverse.POCO.Generator/EF.Reverse.POCO.ttinclude

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -987,31 +987,42 @@ if(tbl.ReverseNavigationProperty.Count() > 0)
987987
<# } #>
988988
<#
989989
foreach(var s in tbl.ReverseNavigationProperty.OrderBy(x => x.Definition))
990-
{
991-
foreach (var rnpda in AdditionalReverseNavigationsDataAnnotations) {#>
992-
[<#=rnpda #>]
993-
<# } #>
994-
<#if(IncludeComments != CommentsStyle.None){#> /// <summary>
990+
{ #>
991+
992+
<# if(IncludeComments != CommentsStyle.None){#> /// <summary>
995993
/// <#=s.Comments ?? "" #>
996994
/// </summary>
997-
<# } #>
995+
<# }
996+
foreach (var rnpda in AdditionalReverseNavigationsDataAnnotations) {#>
997+
[<#=rnpda #>]
998+
<# }
999+
if (s.AdditionalDataAnnotations != null) {
1000+
foreach (var fkda in s.AdditionalDataAnnotations) {#>
1001+
[<#=fkda #>]
1002+
<# }
1003+
} #>
9981004
<#=s.Definition #>
9991005
<# } } #>
10001006
<# if(tbl.HasForeignKey) { #>
10011007

10021008
<#if(IncludeComments != CommentsStyle.None && tbl.Columns.SelectMany(x => x.EntityFk).Any()){#> // Foreign keys
1003-
10041009
<# } #>
10051010
<#
10061011
foreach(var entityFk in tbl.Columns.SelectMany(x => x.EntityFk).OrderBy(o => o.Definition))
1007-
{
1008-
foreach (var fkda in AdditionalForeignKeysDataAnnotations) {#>
1009-
[<#=fkda #>]
1010-
<# } #>
1011-
<#if(IncludeComments != CommentsStyle.None){#> /// <summary>
1012+
{ #>
1013+
1014+
<# if(IncludeComments != CommentsStyle.None){#> /// <summary>
10121015
/// <#=entityFk.Comments #>
10131016
/// </summary>
1014-
<# } #>
1017+
<# }
1018+
foreach (var fkda in AdditionalForeignKeysDataAnnotations) {#>
1019+
[<#=fkda #>]
1020+
<# }
1021+
if (entityFk.AdditionalDataAnnotations != null) {
1022+
foreach (var fkda in entityFk.AdditionalDataAnnotations) {#>
1023+
[<#=fkda #>]
1024+
<# }
1025+
} #>
10151026
<#=entityFk.Definition #>
10161027
<# } } #>
10171028
<#

0 commit comments

Comments
 (0)