public override string BeforeField(AssociationEndModel thatEnd) { if (!thatEnd.IsNavigable) { throw new InvalidOperationException("Cannot call this method if associationEnd is not navigable."); } var annotations = new List <string>(); var sourceEnd = thatEnd.OtherEnd(); if (!sourceEnd.IsCollection && !thatEnd.IsCollection) // one-to-one { annotations.Add($"@{_template.ImportType("javax.persistence.OneToOne")}(optional = {thatEnd.IsNullable.ToString().ToLower()}{(sourceEnd.IsNullable ? "" : ", orphanRemoval = true")})"); if (thatEnd.IsTargetEnd()) { annotations.Add($"@{_template.ImportType("javax.persistence.JoinColumn")}(name=\"{thatEnd.Name.ToSnakeCase()}_id\", nullable = {thatEnd.IsNullable.ToString().ToLower()})"); } } else if (!sourceEnd.IsCollection && thatEnd.IsCollection) // one-to-many { var settings = new List <string>(); if (sourceEnd.IsNavigable) { settings.Add($"mappedBy=\"{sourceEnd.Name.ToCamelCase()}\""); } if (!sourceEnd.IsNullable) { settings.Add("orphanRemoval = true"); } annotations.Add($"@{_template.ImportType("javax.persistence.OneToMany")}({string.Join(", ", settings)})"); } else if (sourceEnd.IsCollection && !thatEnd.IsCollection) // many-to-one { annotations.Add($"@{_template.ImportType("javax.persistence.ManyToOne")}(optional = {thatEnd.IsNullable.ToString().ToLower()})"); //if (thatEnd.IsTargetEnd()) //{ annotations.Add($"@{_template.ImportType("javax.persistence.JoinColumn")}(name=\"{thatEnd.Name.ToSnakeCase()}_id\", nullable = {thatEnd.IsNullable.ToString().ToLower()})"); //} } else if (sourceEnd.IsCollection && thatEnd.IsCollection) // many-to-many { annotations.Add($"@{_template.ImportType("javax.persistence.ManyToMany")}"); if (thatEnd.IsTargetEnd()) { annotations.Add($@"@{_template.ImportType("javax.persistence.JoinTable")}( name = ""{sourceEnd.Element.Name.ToSnakeCase()}_{thatEnd.Element.Name.ToPluralName().ToSnakeCase()}"", joinColumns = {{ @{_template.ImportType("javax.persistence.JoinColumn")}(name = ""{sourceEnd.Element.Name.ToSnakeCase()}_id"") }}, inverseJoinColumns = {{ @{_template.ImportType("javax.persistence.JoinColumn")}(name = ""{thatEnd.Element.Name.ToSnakeCase()}_id"") }} )"); } } return(string.Join(@" ", annotations)); }
public static RelationshipType Relationship(this AssociationEndModel associationEnd) { if ((associationEnd.Multiplicity == Multiplicity.One || associationEnd.Multiplicity == Multiplicity.ZeroToOne) && (associationEnd.OtherEnd().Multiplicity == Multiplicity.One || associationEnd.OtherEnd().Multiplicity == Multiplicity.ZeroToOne)) { return(RelationshipType.OneToOne); } if ((associationEnd.Multiplicity == Multiplicity.One || associationEnd.Multiplicity == Multiplicity.ZeroToOne) && associationEnd.OtherEnd().Multiplicity == Multiplicity.Many) { return(RelationshipType.OneToMany); } if (associationEnd.Multiplicity == Multiplicity.Many && (associationEnd.OtherEnd().Multiplicity == Multiplicity.One || associationEnd.OtherEnd().Multiplicity == Multiplicity.ZeroToOne)) { return(RelationshipType.ManyToOne); } if (associationEnd.Multiplicity == Multiplicity.Many && associationEnd.OtherEnd().Multiplicity == Multiplicity.Many) { return(RelationshipType.ManyToMany); } throw new Exception($"The relationship type from [{associationEnd.Class.Name}] to [{associationEnd.OtherEnd().Class.Name}] could not be determined."); }
public static RelationshipType Relationship(this AssociationEndModel associationEnd) { if (!associationEnd.IsCollection && !associationEnd.OtherEnd().IsCollection) { return(RelationshipType.OneToOne); } if (!associationEnd.IsCollection && associationEnd.OtherEnd().IsCollection) { return(RelationshipType.OneToMany); } if (associationEnd.IsCollection && !associationEnd.OtherEnd().IsCollection) { return(RelationshipType.ManyToOne); } if (associationEnd.IsCollection && associationEnd.OtherEnd().IsCollection) { return(RelationshipType.ManyToMany); } throw new Exception($"The relationship type from [{associationEnd.Element.Name}] to [{associationEnd.OtherEnd().Element.Name}] could not be determined."); }
public override string AssociationAfter(AssociationEndModel associationEnd) { if (!associationEnd.IsNavigable) { return(base.AssociationAfter(associationEnd)); } var name = Template.Types.InContext(DomainEntityStateTemplate.InterfaceContext).Get(associationEnd).Name; return($@" {Template.NormalizeNamespace(name)} I{associationEnd.OtherEnd().Class.Name}.{associationEnd.Name().ToPascalCase()} => {associationEnd.Name().ToPascalCase()}; "); }
public override string PropertyBefore(AssociationEndModel associationEnd) { if (associationEnd.RequiresForeignKey()) { if (associationEnd.OtherEnd().Element.HasStereotype("Foreign Key")) { return(base.PropertyBefore(associationEnd)); } var foreignKeyType = associationEnd.Class.GetSurrogateKeyType(Template.Types) ?? Template.UseType(_foreignKeyType); return($@" {foreignKeyType}{ (associationEnd.IsNullable ? "?" : "") } { associationEnd.Name().ToPascalCase() }Id {{ get; }}"); } return(base.PropertyBefore(associationEnd)); }
private static string GetForeignKeyLambda(AssociationEndModel associationEnd) { var columns = ((associationEnd.IsSourceEnd() ? (associationEnd as AssociationSourceEndModel).GetForeignKey()?.ColumnName() : (associationEnd as AssociationTargetEndModel).GetForeignKey()?.ColumnName()) ?? associationEnd.OtherEnd().Name.ToPascalCase() + "Id") .Split(',') // upgrade stereotype to have a selection list. .Select(x => x.Trim()) .ToList(); if (columns.Count == 1) { return $"x => x.{columns.Single()}"; } return $"x => new {{ {string.Join(", ", columns.Select(x => "x." + x))}}}"; }
public override string AssociationBefore(AssociationEndModel associationEnd) { if (!associationEnd.IsNavigable && associationEnd.Multiplicity == Multiplicity.One && associationEnd.OtherEnd().Multiplicity == Multiplicity.Many) { return($@" public virtual { Template.GetTypeName(associationEnd) } { associationEnd.Name() } {{ get; set; }} "); } if (!associationEnd.IsNavigable && associationEnd.Multiplicity == Multiplicity.Many && associationEnd.OtherEnd().Multiplicity == Multiplicity.Many) { return($@" public virtual { Template.GetTypeName(associationEnd) } { associationEnd.Name() } {{ get; set; }} "); } return(base.AssociationBefore(associationEnd)); }
private static bool IsManyToVariantsOfOne(AssociationEndModel associationEnd) { return((associationEnd.Multiplicity == Multiplicity.One || associationEnd.Multiplicity == Multiplicity.ZeroToOne) && associationEnd.OtherEnd().Multiplicity == Multiplicity.Many); }
private string GetAssociationMapping(AssociationEndModel associationEnd) { var statements = new List<string>(); switch (associationEnd.Association.GetRelationshipType()) { case RelationshipType.OneToOne: statements.Add($"builder.HasOne(x => x.{associationEnd.Name.ToPascalCase()})"); statements.Add($".WithOne({ (associationEnd.OtherEnd().IsNavigable ? $"x => x.{associationEnd.OtherEnd().Name.ToPascalCase()}" : "") })"); statements.Add($".HasForeignKey<{ Model.Name }>({GetForeignKeyLambda(associationEnd.OtherEnd())})"); if (!associationEnd.OtherEnd().IsNullable) { statements.Add($".IsRequired()"); statements.Add($".OnDelete(DeleteBehavior.Cascade)"); } else { statements.Add($".OnDelete(DeleteBehavior.Restrict)"); } break; case RelationshipType.ManyToOne: statements.Add($"builder.HasOne(x => x.{associationEnd.Name.ToPascalCase()})"); statements.Add($".WithMany({ (associationEnd.OtherEnd().IsNavigable ? "x => x." + associationEnd.OtherEnd().Name.ToPascalCase() : "") })"); statements.Add($".HasForeignKey({GetForeignKeyLambda(associationEnd.OtherEnd())})"); statements.Add($".OnDelete(DeleteBehavior.Restrict)"); break; case RelationshipType.OneToMany: statements.Add($"builder.HasMany(x => x.{associationEnd.Name.ToPascalCase()})"); statements.Add($".WithOne(x => x.{ associationEnd.OtherEnd().Name.ToPascalCase() })"); statements.Add($".HasForeignKey({GetForeignKeyLambda(associationEnd)})"); if (!associationEnd.OtherEnd().IsNullable) { statements.Add($".IsRequired()"); statements.Add($".OnDelete(DeleteBehavior.Cascade)"); } break; case RelationshipType.ManyToMany: if (Project.GetProject().IsNetCore2App || Project.GetProject().IsNetCore3App) { statements.Add($"builder.Ignore(x => x.{associationEnd.Name.ToPascalCase()})"); Logging.Log.Warning($@"Intent.EntityFrameworkCore: Cannot create mapping relationship from {Model.Name} to {associationEnd.Class.Name}. It has been ignored, and will not be persisted. Many-to-Many relationships are not yet supported by EntityFrameworkCore as yet. Either upgrade your solution to .NET 5.0 or create a joining-table entity (e.g. [{Model.Name}] 1 --> * [{Model.Name}{associationEnd.Class.Name}] * --> 1 [{associationEnd.Class.Name}]) For more information, please see https://github.com/aspnet/EntityFrameworkCore/issues/1368"); } else // if .NET 5.0 or above... { statements.Add($"builder.HasMany(x => x.{associationEnd.Name.ToPascalCase()})"); statements.Add($".WithMany(x => x.{associationEnd.OtherEnd().Name.ToPascalCase()})"); statements.Add($".UsingEntity(x => x.ToTable(\"{associationEnd.OtherEnd().Class.Name}{associationEnd.Class.Name.ToPluralName()}\"))"); } break; default: throw new Exception($"Relationship type for association [{Model.Name}.{associationEnd.Name}] could not be determined."); } return $@" {string.Join(@" ", statements)};"; }
private static bool RequiresForeignKeyOnAssociatedEnd(AssociationEndModel associationEnd) { return(associationEnd.Multiplicity == Multiplicity.Many && (associationEnd.Association.AssociationType == AssociationType.Composition || associationEnd.OtherEnd().IsNavigable)); }
private static string[] GetForeignKeys(AssociationEndModel associationEnd) { return(associationEnd.Element.GetStereotypeProperty("Foreign Key", "Column Name", associationEnd.OtherEnd().Name().ToPascalCase() + "Id") .Split(',') .Select(x => x.Trim()) .ToArray()); }
public void MapOneToOne(AssociationEndModel associationEnd) { var parent = associationEnd.Association.SourceEnd; var child = associationEnd.Association.TargetEnd; string hasClause = !associationEnd.IsNullable ? "HasRequired" : "HasOptional"; string withClause = "With" + (!associationEnd.OtherEnd().IsNullable ? "Required" : "Optional") + ((!associationEnd.IsNullable) == (!associationEnd.OtherEnd().IsNullable) ? DeterminePrinciple(associationEnd) : ""); #line default #line hidden #line 225 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write(" "); #line default #line hidden #line 226 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Format("this.{0}(x => x.{1})", hasClause, associationEnd.Name().ToPascalCase()))); #line default #line hidden #line 226 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write("\r\n "); #line default #line hidden #line 227 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Format(".{0}({1})", withClause, associationEnd.OtherEnd().IsNavigable ? "x => x." + associationEnd.OtherEnd().Name().ToPascalCase(): ""))); #line default #line hidden #line 227 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write("\r\n"); #line default #line hidden #line 228 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" if (((associationEnd.Association.AssociationType == AssociationType.Composition && associationEnd.Association.RelationshipString() == "0..1->1") || (associationEnd.Association.AssociationType == AssociationType.Aggregation && associationEnd.Association.RelationshipString() == "0..1->1")) && Model.Attributes.All(a => a.Name.ToPascalCase() != associationEnd.OtherEnd().Class.GetStereotypeProperty("Foreign Key", "Column Name", associationEnd.Name().ToPascalCase() + "Id").ToPascalCase())) { #line default #line hidden #line 231 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write(" .Map(m => m.MapKey(\""); #line default #line hidden #line 232 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(associationEnd.OtherEnd().Class.GetStereotypeProperty("Foreign Key", "Column Name", associationEnd.Name().ToPascalCase() + "Id"))); #line default #line hidden #line 232 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write("\"))\r\n"); #line default #line hidden #line 233 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" } #line default #line hidden #line 234 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" if (associationEnd.Association.AssociationType == AssociationType.Composition) { #line default #line hidden #line 234 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write(" .WillCascadeOnDelete()\r\n"); #line default #line hidden #line 236 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" } #line default #line hidden #line 236 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" this.Write(" ;\r\n"); #line default #line hidden #line 238 "C:\Dev\Intent.Modules.NET\Modules\Intent.Modules.EntityFramework\Templates\EFMapping\EFMappingTemplate.tt" }