2

Hi I have an entity as below

public class SalaryTransactionAudit
{
      public long SalaryTransactionAuditId { get; set; }
      public Guid TransactionBatchId { get; set; }
      public DateTime UploadedDate { get; set; }
      public string UploadedBy { get; set; }
      public long SalaryTransactionStatusId { get; set; }
}

The above entity has primary key on SalaryTransactionAuditId and Alternate Key on TransactionBatchId as below

public class SalaryTransactionAuditConfiguration : IEntityTypeConfiguration<SalaryTransactionAudit>
{
        public void Configure(EntityTypeBuilder<SalaryTransactionAudit> builder)
        {
            builder.ToTable("SalaryTransactionAudit");
            builder.HasKey(e => e.SalaryTransactionAuditId);
            builder.HasAlternateKey(e => e.TransactionBatchId);
        }
 }

And I also have this entity

public class SalaryTransaction
 {
        public long SalaryTransactionId { get; set; }
        public Guid TransactionBatchId { get; set; }
        public long EmployeeId { get; set; }
        public int AnnualSalary { get; set; }
        public int SuperRate { get; set; }
        public int PaymentPeriodYear { get; set; }
        public int PaymentPeriodMonth { get; set; }

        public Employee Employee { get; set; }
   }

How do I configure (using fluent API) for FK Constraint on TransactionBatchId something like below

public class SalaryTransactionConfiguration : IEntityTypeConfiguration<SalaryTransaction>
{
        public void Configure(EntityTypeBuilder<SalaryTransaction> builder)
        {
            builder.ToTable("SalaryTransaction");
            builder.HasKey(e => e.SalaryTransactionId);
            builder.HasForeignKey(e => e.TransactionBatchId );

        }
} 
TanvirArjel
  • 30,049
  • 14
  • 78
  • 114
Alan B
  • 2,219
  • 4
  • 32
  • 62

2 Answers2

9

Foregn / principal keys of a relationship are configured via relationship builders HasForeignKey / HasPrincipalKey fluent API.

It would be good if you add navigation property at least to one of the related entities. But with the current model, and assuming the relationship is one-to-many, it could be something like this:

Inside SalaryTransactionConfiguration class

builder
    .HasOne<SalaryTransactionAudit>()
    .WithMany()
    .HasForeignKey(e => e.TransactionBatchId)
    .HasPrincipalKey(e => e.TransactionBatchId);

or inside SalaryTransactionAuditConfiguration class

builder
    .HasMany<SalaryTransaction>()
    .WithOne()
    .HasForeignKey(e => e.TransactionBatchId)
    .HasPrincipalKey(e => e.TransactionBatchId);

Relationships always have two ends, so when using entity type configuration classes, put the configuration in either of them, but not both (to avoid redundant or confliction configuration for one and the same relationship). Also make sure to use Has / With methods correctly, i.e. with or without navigation property expression depending of whether it exists or not.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • It should be noted that nullable values aren't permitted for an alternate key field, see [Optional alternate key properties](https://github.com/dotnet/efcore/issues/4415) issue and upvote if you need this ability. – Mark G Jun 04 '20 at 20:00
0

You can try to use DataAnnotation something like this:

public Guid TransactionBatchId { get; set; }

[ForeignKey("TransactionBatchId")]  
public SalaryTransactionAudit SalaryTransactionAudit { get; set; }

See also: MSDN

Leon
  • 443
  • 5
  • 19
  • I don't believe this is correct, it would try to map the [TransactionBatchId] field to the primary key field on the SalaryTransactionAudit table which is [SalaryTransactionAuditId]. – Ryan Mar 09 '23 at 15:56