# IT:AD:EF/CodeFirst/FluentAPI/Relationships/Examples # * [[../|(UP)]] {{indexmenu>.#2|nsort tsort}} Required Lookup Value: modelBuilder.Entity() .HasRequired(wi => wi.LoanMaintenanceType) .WithMany() .HasForeignKey(wi => wi.LoanMaintenanceTypeFK); More Complex is the following set of 3: //Create 1 to 1 'parent' BankWorkInstruction: modelBuilder.Entity() .HasRequired(bcwi => bcwi.BankWorkInstruction) .WithRequiredDependent(); modelBuilder.Entity() .HasMany(bcwi => bcwi.Customers) .WithRequired() .HasForeignKey(bc => bc.BankCustomerWorkInstructionFK); //.WithRequiredDependent(); // not sure if required - can't run yet //modelBuilder.Entity() // .Property(wi => wi.BankWorkInstructionFK) // .IsRequired(); //Create Relationships between individual WF's and base wf: modelBuilder.Entity() .HasRequired(wi => wi.BankCustomerWorkInstruction) .WithOptional(); //MAY HAVE TO .WillCascadeOnDelete(false); For Many to One (Invoice/LineItems): modelBuilder.Entity() .HasMany(bcwi => bcwi.LineItems) .WithRequired() .HasForeignKey(bc => bc.InvoiceFK); Many more: using System.Data.Entity; using System.Diagnostics; using Nab.Wdms.PM.Domain; using Nab.Wdms.PM.Infrastructure.Services; using XAct.Services; namespace Nab.Wdms.PM.Infrastructure.Data { [DefaultBindingImplementation(typeof(ICoreDbModelBuilder))] public class CoreDbModelBuilder : ICoreDbModelBuilder { private readonly ITracingService _tracingService; public CoreDbModelBuilder(ITracingService tracingService) { _tracingService = tracingService; } public void OnModelCreating(DbModelBuilder modelBuilder) { _tracingService.Trace(TraceLevel.Verbose, "OnModelBuilding:Begin...:{0}", this); //Using FluentAPI rather than DataAnnotations avoids having //poluting model with EF dependency rising up beyond Data layer CreateCoreRelationships(modelBuilder); CreateCoreRequirements(modelBuilder); _tracingService.Trace(TraceLevel.Verbose, "OnModelBuilding:Complete:{0}", this); } private void CreateCoreRelationships(DbModelBuilder modelBuilder) { _tracingService.Trace(TraceLevel.Verbose, "--OnModelBuilding:{1}:.......:{0}", this, "CreateCoreRelationships"); modelBuilder.Entity() .HasRequired(wi => wi.WorkInstructionType) .WithMany() .HasForeignKey(wi => wi.WorkInstructionTypeFK); modelBuilder.Entity() .HasMany(wi => wi.Comments) .WithRequired() .HasForeignKey(n => n.ParentFK); modelBuilder.Entity() .HasRequired(n => n.NoteParentType) .WithMany() .HasForeignKey(n => n.NoteParentTypeFK); modelBuilder.Entity() .HasMany(wi => wi.Attachments) .WithRequired() .HasForeignKey(a => a.ParentFK); modelBuilder.Entity() .HasRequired(a => a.AttachmentParentType) .WithMany() .HasForeignKey(a => a.AttachmentParentTypeFK); modelBuilder.Entity() .HasRequired(a => a.AttachmentProviderType) .WithMany() .HasForeignKey(a => a.ProviderFK); modelBuilder.Entity() .HasOptional(a => a.DocumentType) .WithMany() .HasForeignKey(a => a.DocumentTypeFK); modelBuilder.Entity() .HasRequired(a => a.Attachment) .WithMany() .HasForeignKey(a => a.AttachmentId); modelBuilder.Entity() .HasRequired(wi => wi.WorkInstructionSchema) .WithMany() .HasForeignKey(wi => wi.WorkInstructionSchemaFK); modelBuilder.Entity() .HasRequired(wi => wi.WorkflowEngine) .WithMany() .HasForeignKey(wi => wi.WorkflowEngineFK); } private void CreateCoreRequirements(DbModelBuilder modelBuilder) { _tracingService.Trace(TraceLevel.Verbose, "--OnModelBuilding:.......:{0}:{1}", this, "CreateCoreRequirements"); modelBuilder.Entity() .Property(wi => wi.StateRaw) .IsRequired(); //modelBuilder.Entity() // .Property(wi => wi.StartDateTime) // .IsRequired(); modelBuilder.Entity() .Property(wi => wi.Tag) .IsRequired(); //modelBuilder.Entity() // .Property(wi => wi.WorkFlowEngineFK) // .IsRequired(); //modelBuilder.Entity() // .Property(wi => wi.WorkInstructionTypeFK) // .IsRequired(); //modelBuilder.Entity() // .Property(wi => wi.WorkflowProcessSerializedId) // .IsRequired(); modelBuilder.Entity() .Property(wi => wi.DisplayName) .IsRequired(); // modelBuilder.Entity() //.Property(wi => wi.WorkflowEngineFK) //.IsRequired(); modelBuilder.Entity() .Property(wi => wi.WorkflowUrl) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.Name) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.Url) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.Name) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.CreatedBy) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.CreatedOn) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.Name) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.ParentFK) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.DocumentStoreId) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.CreatedBy) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.CreatedOn) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.ParentFK) .IsRequired(); modelBuilder.Entity() .Property(wi => wi.Text) .IsRequired(); } } } using System.Data.Entity; using System.Diagnostics; using Nab.Wdms.PM.Domain; using Nab.Wdms.PM.Infrastructure.Services; using XAct.Services; namespace Nab.Wdms.PM.Infrastructure.Data { [DefaultBindingImplementation(typeof(IM01DbModelBuilder))] public class M01DbModuleBuilder : IM01DbModelBuilder { private readonly ITracingService _tracingService; public M01DbModuleBuilder(ITracingService tracingService) { _tracingService = tracingService; } public void OnModelCreating(DbModelBuilder modelBuilder) { _tracingService.Trace(TraceLevel.Verbose, "OnModelBuilding:Begin...:{0}", this); //Using FluentAPI rather than DataAnnotations avoids having //poluting model with EF dependency rising up beyond Data layer CreateRoutingRuleRelationShips(modelBuilder); CreateM01BankWorkInstructionRelationships(modelBuilder); CreateM01LookupRelationships(modelBuilder); CreateM01WorkflowRelationships(modelBuilder); CreateM01WorkflowLookupRelationships(modelBuilder); CreateM01WorkflowConstraints(modelBuilder); CreateWorkflowStepConstraints(modelBuilder); _tracingService.Trace(TraceLevel.Verbose, "OnModelBuilding:Complete:{0}", this); } private void CreateRoutingRuleRelationShips(DbModelBuilder modelBuilder) { modelBuilder.Entity() .HasKey(m => m.Id); modelBuilder.Entity() .HasMany(m => m.Rules) .WithRequired() .HasForeignKey(m => m.RuleSetFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasKey(m => m.Id); modelBuilder.Entity() .HasOptional(m=>m.Location) .WithMany() .HasForeignKey(m=>m.LocationFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(m=>m.ParentWorkInstructionType) .WithMany() .HasForeignKey(m=>m.ParentWorkInstructionTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(m=>m.WorkInstructionType) .WithMany() .HasForeignKey(m=>m.WorkInstructionTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasRequired(m=>m.WorkflowStep) .WithMany() .HasForeignKey(m=>m.WorkflowStepFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .Property(m=>m.RequiresSpecialRules) .IsRequired(); modelBuilder.Entity() .Property(m=>m.ResultingGroups) .IsRequired(); modelBuilder.Entity() .HasMany(m => m.AdditionalData) .WithRequired() .HasForeignKey(m=>m.RuleFK) .WillCascadeOnDelete(false); } private void CreateWorkflowStepConstraints(DbModelBuilder modelBuilder) { modelBuilder.Entity() .HasKey(m=>m.Id); modelBuilder.Entity() .Property(m => m.Name).IsRequired(); modelBuilder.Entity() .Property(m => m.Description).IsOptional(); } private void CreateM01BankWorkInstructionRelationships(DbModelBuilder modelBuilder) { _tracingService.Trace(TraceLevel.Verbose, "--OnModelBuilding:.......:{0}:{1}", this, "CreateM01BankWorkInstructionRelationships"); //*-1 back to Core BankWorkInstruction: modelBuilder.Entity() .HasRequired(bwi => bwi.WorkInstruction) .WithOptional(); //MAY HAVE TO .WillCascadeOnDelete(false); //*-1:to Lookup modelBuilder.Entity() .HasRequired(bwi => bwi.Location) .WithMany() .HasForeignKey(bwi => bwi.LocationFK); //*-1:to Lookup modelBuilder.Entity() .HasOptional(wi => wi.InitiatingChannel) .WithMany() .HasForeignKey(wi => wi.InitiatingChannelFK); // not sure if required - can't run yet //modelBuilder.Entity() // .Property(wi => wi.WorkInstructionFK) // .IsRequired(); //modelBuilder.Entity() // .Property(wi => wi.LocationFK) // .IsRequired(); //modelBuilder.Entity() // .Property(wi => wi.InitiatingChannelFK) // .IsRequired(); } private void CreateM01LookupRelationships(DbModelBuilder modelBuilder) { _tracingService.Trace(TraceLevel.Verbose, "--OnModelBuilding:.......:{0}:{1}", this, "CreateM01LookupRelationships"); //Create 1 to 1 'parent' BankWorkInstruction: modelBuilder.Entity() .HasRequired(bcwi => bcwi.BankWorkInstruction) .WithRequiredDependent(); modelBuilder.Entity() .HasMany(bcwi => bcwi.Customers) .WithRequired() .HasForeignKey(bc => bc.BankCustomerWorkInstructionFK); modelBuilder.Entity() .Property(m => m.Account) .HasMaxLength(EntityAndDatabaseConstants.AccountLength) .IsFixedLength(); // not sure if required - can't run yet //modelBuilder.Entity() // .Property(wi => wi.BankWorkInstructionFK) // .IsRequired(); } private void CreateM01WorkflowRelationships(DbModelBuilder modelBuilder) { _tracingService.Trace(TraceLevel.Verbose, "--OnModelBuilding:.......:{0}:{1}", this, "CreateM01WorkflowRelationships"); //--------------------------------------------------------- //Create Relationships between individual WF's and base wf: modelBuilder.Entity() .HasRequired(wi => wi.BankCustomerWorkInstruction) .WithOptional(); modelBuilder.Entity() .HasRequired(wi => wi.BankCustomerWorkInstruction) .WithOptional(); //MAY HAVE TO .WillCascadeOnDelete(false); modelBuilder.Entity() .HasRequired(wi => wi.BankCustomerWorkInstruction) .WithOptional(); //MAY HAVE TO .WillCascadeOnDelete(false); modelBuilder.Entity() .HasRequired(wi => wi.BankCustomerWorkInstruction) .WithOptional(); //MAY HAVE TO .WillCascadeOnDelete(false); modelBuilder.Entity() .HasRequired(wi => wi.BankCustomerWorkInstruction) .WithOptional(); modelBuilder.Entity() .HasRequired(wi => wi.BankCustomerWorkInstruction) .WithOptional(); modelBuilder.Entity() .HasRequired(wi => wi.BankCustomerWorkInstruction) .WithOptional(); } private void CreateM01WorkflowLookupRelationships(DbModelBuilder modelBuilder) { _tracingService.Trace(TraceLevel.Verbose, "--OnModelBuilding:.......:{0}:{1}", this, "CreateM01WorkflowLookupRelationships"); // ------ M01WF01 modelBuilder.Entity() .HasOptional(wi => wi.AccountType) .WithMany() .HasForeignKey(wi => wi.AccountTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.FxCompleteOption) .WithMany() .HasForeignKey(wi => wi.FxCompleteFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.PhysicalsStoredAndOriginalsOption) .WithMany() .HasForeignKey(wi => wi.PhysicalsStoredAndOriginalsOptionFK) .WillCascadeOnDelete(false); // ------ M01WF02 modelBuilder.Entity() .HasOptional(wi => wi.BankBuyCurrencyType) .WithMany() .HasForeignKey(wi => wi.BankBuyCurrencyTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.BankSellCurrencyType) .WithMany() .HasForeignKey(wi => wi.BankSellCurrencyTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.CurrencyType) .WithMany() .HasForeignKey(wi => wi.CurrencyTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.FxCompleteOption) .WithMany() .HasForeignKey(wi => wi.FxCompleteFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.PhysicalsStoredAndOriginalsOption) .WithMany() .HasForeignKey(wi => wi.PhysicalsStoredAndOriginalsOptionFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.RollOverInstructionType) .WithMany() .HasForeignKey(wi => wi.RollOverInstructionTypeFK) .WillCascadeOnDelete(false); // ------ M01WF03 modelBuilder.Entity() .HasOptional(wi => wi.BankBuyCurrencyType) .WithMany() .HasForeignKey(wi => wi.BankBuyCurrencyTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.BankSellCurrencyType) .WithMany() .HasForeignKey(wi => wi.BankSellCurrencyTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.PhysicalsStoredAndOriginalsOption) .WithMany() .HasForeignKey(wi => wi.PhysicalsStoredAndOriginalsOptionFK) .WillCascadeOnDelete(false); // ------ M01WF04 modelBuilder.Entity() .HasOptional(wi => wi.BankBuyCurrencyType) .WithMany() .HasForeignKey(wi => wi.BankBuyCurrencyTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.BankSellCurrencyType) .WithMany() .HasForeignKey(wi => wi.BankSellCurrencyTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.CollateralReleaseOption) .WithMany() .HasForeignKey(wi => wi.CollateralReleaseFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.FxCompleteOption) .WithMany() .HasForeignKey(wi => wi.FxCompleteFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.LoanMaintenanceType) .WithMany() .HasForeignKey(wi => wi.LoanMaintenanceTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.PhysicalsStoredAndOriginalsOption) .WithMany() .HasForeignKey(wi => wi.PhysicalsStoredAndOriginalsOptionFK) .WillCascadeOnDelete(false); // ------ M01WF05 modelBuilder.Entity() .HasOptional(wi => wi.PhysicalsStoredAndOriginalsOption) .WithMany() .HasForeignKey(wi => wi.PhysicalsStoredAndOriginalsOptionFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.RoutingType) .WithMany() .HasForeignKey(wi => wi.RoutingTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.TeamType) .WithMany() .HasForeignKey(wi => wi.TeamTypeFK) .WillCascadeOnDelete(false); // ------ M01WF06 modelBuilder.Entity() .HasOptional(wi => wi.BankBuyCurrencyType) .WithMany() .HasForeignKey(wi => wi.BankBuyCurrencyTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.BankSellCurrencyType) .WithMany() .HasForeignKey(wi => wi.BankSellCurrencyTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.FxCompleteOption) .WithMany() .HasForeignKey(wi => wi.FxCompleteFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.PaymentInType) .WithMany() .HasForeignKey(wi => wi.PaymentInTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.PaymentOutType) .WithMany() .HasForeignKey(wi => wi.PaymentOutTypeFK) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasOptional(wi => wi.PhysicalsStoredAndOriginalsOption) .WithMany() .HasForeignKey(wi => wi.PhysicalsStoredAndOriginalsOptionFK) .WillCascadeOnDelete(false); } private void CreateM01WorkflowConstraints(DbModelBuilder modelBuilder) { _tracingService.Trace(TraceLevel.Verbose, "OnModelBuilding:.......:{0}:{1}", this, "CreateM01WorkflowConstraints"); modelBuilder.Entity() .Property(m => m.CustomerNumber) .HasMaxLength(EntityAndDatabaseConstants.CustomerNumberLength) .IsFixedLength() .IsRequired(); // ------ M01WF01 //modelBuilder.Entity() // .Property(m => m.Account) // .HasMaxLength(EntityAndDatabaseConstants.AccountLength); // ------ M01WF02 modelBuilder.Entity() .Property(m => m.ConfirmationExt) .HasMaxLength(EntityAndDatabaseConstants.ConfirmationExtensionLength); ////SKY12831A: //modelBuilder.Entity() // .Property(m => m.Account) // .HasMaxLength(EntityAndDatabaseConstants.AccountLength) // .IsFixedLength(); modelBuilder.Entity() .Property(m => m.DepositAmount) .HasPrecision(EntityAndDatabaseConstants.MoneyLength, EntityAndDatabaseConstants.MoneyDecimalPlaces); modelBuilder.Entity() .Property(m => m.DepositCustomerRate) .HasPrecision(EntityAndDatabaseConstants.PercentageSevenLength, EntityAndDatabaseConstants.PercentageFourDecimalPlaces); modelBuilder.Entity() .Property(m => m.BankBuyCurrencyAmount) .HasPrecision(EntityAndDatabaseConstants.MoneyLength, EntityAndDatabaseConstants.MoneyDecimalPlaces); modelBuilder.Entity() .Property(m => m.BankSellCurrencyAmount) .HasPrecision(EntityAndDatabaseConstants.MoneyLength, EntityAndDatabaseConstants.MoneyDecimalPlaces); modelBuilder.Entity() .Property(m => m.CustomerRate) .HasPrecision(EntityAndDatabaseConstants.PercentageSevenLength, EntityAndDatabaseConstants.PercentageFourDecimalPlaces); modelBuilder.Entity() .Property(m => m.DealerRate) .HasPrecision(EntityAndDatabaseConstants.PercentageSevenLength, EntityAndDatabaseConstants.PercentageFourDecimalPlaces); modelBuilder.Entity() .Property(m => m.FxPurpose) .HasMaxLength(EntityAndDatabaseConstants.FxPurposeLength); //modelBuilder.Entity() // .Property(m =>m.TenureYears) // ------ M01WF03 //////SKY12831A: //modelBuilder.Entity() // .Property(m => m.Account) // .HasMaxLength(EntityAndDatabaseConstants.AccountLength) // .IsFixedLength(); modelBuilder.Entity() .Property(m => m.FxPurpose) .HasMaxLength(EntityAndDatabaseConstants.FxPurposeLength); modelBuilder.Entity() .Property(m => m.BankBuyCurrencyAmount) .HasPrecision(EntityAndDatabaseConstants.MoneyLength, EntityAndDatabaseConstants.MoneyDecimalPlaces); modelBuilder.Entity() .Property(m => m.BankSellCurrencyAmount) .HasPrecision(EntityAndDatabaseConstants.MoneyLength, EntityAndDatabaseConstants.MoneyDecimalPlaces); modelBuilder.Entity() .Property(m => m.CustomerRate) .HasPrecision(EntityAndDatabaseConstants.PercentageSevenLength, EntityAndDatabaseConstants.PercentageFourDecimalPlaces); modelBuilder.Entity() .Property(m => m.DealerRate) .HasPrecision(EntityAndDatabaseConstants.PercentageSevenLength, EntityAndDatabaseConstants.PercentageFourDecimalPlaces); // ------ M01WF04 ////SKY12831A: //modelBuilder.Entity() // .Property(m => m.Account) // .HasMaxLength(EntityAndDatabaseConstants.AccountLength) // .IsFixedLength(); modelBuilder.Entity() .Property(m => m.FxPurpose) .HasMaxLength(EntityAndDatabaseConstants.FxPurposeLength); modelBuilder.Entity() .Property(m => m.BankBuyCurrencyAmount) .HasPrecision(EntityAndDatabaseConstants.MoneyLength, EntityAndDatabaseConstants.MoneyDecimalPlaces); modelBuilder.Entity() .Property(m => m.BankSellCurrencyAmount) .HasPrecision(EntityAndDatabaseConstants.MoneyLength, EntityAndDatabaseConstants.MoneyDecimalPlaces); modelBuilder.Entity() .Property(m => m.CustomerRate) .HasPrecision(EntityAndDatabaseConstants.PercentageSevenLength, EntityAndDatabaseConstants.PercentageFourDecimalPlaces); modelBuilder.Entity() .Property(m => m.DealerRate) .HasPrecision(EntityAndDatabaseConstants.PercentageSevenLength, EntityAndDatabaseConstants.PercentageFourDecimalPlaces); modelBuilder.Entity() .Property(m => m.ConfirmationExt) .HasMaxLength(EntityAndDatabaseConstants.ConfirmationExtensionLength); // ------ M01WF05 //SKY12831A: //modelBuilder.Entity() // .Property(m => m.Account) // .HasMaxLength(EntityAndDatabaseConstants.AccountLength) // .IsFixedLength(); // ------ M01WF06 ////SKY12831A: //modelBuilder.Entity() // .Property(m => m.Account) // .HasMaxLength(EntityAndDatabaseConstants.AccountLength) // .IsFixedLength(); modelBuilder.Entity() .Property(m => m.FxPurpose) .HasMaxLength(EntityAndDatabaseConstants.FxPurposeLength); modelBuilder.Entity() .Property(m => m.BankBuyCurrencyAmount) .HasPrecision(EntityAndDatabaseConstants.MoneyLength, EntityAndDatabaseConstants.MoneyDecimalPlaces); modelBuilder.Entity() .Property(m => m.BankSellCurrencyAmount) .HasPrecision(EntityAndDatabaseConstants.MoneyLength, EntityAndDatabaseConstants.MoneyDecimalPlaces); modelBuilder.Entity() .Property(m => m.CustomerRate) .HasPrecision(EntityAndDatabaseConstants.PercentageSevenLength, EntityAndDatabaseConstants.PercentageFourDecimalPlaces); modelBuilder.Entity() .Property(m => m.DealerRate) .HasPrecision(EntityAndDatabaseConstants.PercentageSevenLength, EntityAndDatabaseConstants.PercentageFourDecimalPlaces); modelBuilder.Entity() .Property(m => m.ConfirmationExt) .HasMaxLength(EntityAndDatabaseConstants.ConfirmationExtensionLength); } } }