I have two entities Payroll
and Entries
which have one to many relationship. Multiple entries can be associated to a payroll. Basically, during the newly payroll creation, entries needs to be associated with the PayrollId
and for that I have wrote the below mentioned code to achieve the whole changes in single SaveChanges()
.
Payroll
entity:
public class Payroll : BaseEntity, ITrackCreated, ITrackUpdated
{
public int PayrollId { get; set; }
public string Name { get; set; }
public PayrollStatus Status { get; set; }
public decimal Amount { get; set; }
public List<Entries> Entries {get;set;}
}
Entries
entity:
public class Entries : BaseEntity, ITrackCreated, ITrackUpdated
{
public int EntryId { get; set; }
public EntryType EntryType { get; set; }
public DateTime EntryDate { get; set; }
public Decimal Amount { get; set; }
public EntryStatus Status { get; set; }
public int? PayrollId { get; set; }
public virtual Payroll Payroll {get;set;}
}
Entities relation:
public EntriesConfiguration(ModelBuilder modelBuilder) : base(modelBuilder)
{
base.Configure();
Builder.HasKey(t => t.EntryId);
Builder.Property(p => p.EntryId).ValueGeneratedOnAdd();
Builder.HasOne(x => x.Payroll).WithMany(x => x.Entries).HasForeignKey(x => x.PayrollId);
Builder.ToTable("Entries");
}
Code for the payroll creation and payrollId
update to entries:
foreach (var entryGroup in groups)
{
var creditEntries = await _commonDbFunction.GetCreditEntries(entryGroup, EntryStatus.Pending);
var debitEntries = await _commonDbFunction.GetDebitEntries(entryGroup, EntryStatus.Pending);
exceptionPayrollDetail = CreatePayroll(payrollDetail);
// binding data in payroll entity model
await _applicationDbContext.Payrolls.AddAsync(exceptionPayrollDetail);
creditEntries?.ForEach(x => x.PayrollId = exceptionPayrollDetail?.PayrollId);
//updating payrollId of above model in Entries Table
debitEntries?.ForEach(x => x.PayrollId = exceptionPayrollDetail?.PayrollId);
//updating payrollId of above model in Entries Table
await _applicationDbContext.SaveChangesAsync();
// calling single SaveChanges adding payroll and updating enries.
}
Please suggest the way to achieve the same in single SaveChanges()
as 0 PayrollId
is not allowing to save the data in Entries
table also payrollId
should be greater than zero while updating in entries.
Thanks in advance..
CodePudding user response:
since the exceptionPayrollDetail
is not yet persisted to the db, the exceptionPayrollDetail?.PayrollId
will always be zero.
may be you can call SaveChangesAsync()
after await _applicationDbContext.Payrolls.AddAsync(exceptionPayrollDetail);
, then this would have the PayrollId
generated
CodePudding user response:
You can set the navigation property itself, not the id, if you need.
Slightly simplified example:
public class ApplicationContext : DbContext
{
public DbSet<Entries> Entries { get; set; }
public DbSet<Payroll> Payrolls { get; set; }
public string DbPath { get; }
public ApplicationContext()
{
DbPath = System.IO.Path.Join(@"D:\Work\Envisability\EFCorePlayground\EFCorePlayground", "blogging.db");
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite($"Data Source={DbPath}");
//options.LogTo(Console.WriteLine);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var entriesBuilder = modelBuilder.Entity<Entries>();
entriesBuilder.Property(p => p.EntryId).ValueGeneratedOnAdd();
entriesBuilder.HasOne(x => x.Payroll).WithMany(x => x.Entries).HasForeignKey(x => x.PayrollId);
entriesBuilder.HasKey(t => t.EntryId);
entriesBuilder.ToTable("Entries");
}
public void Seed()
{
if (Entries.Any() || Payrolls.Any()) return;
var entries = new List<Entries>
{
new Entries{ Name="e1" },
new Entries{ Name="e2" },
new Entries{ Name="e3" }
};
var payrolls = new List<Payroll>
{
new Payroll{ Name = "1" },
new Payroll{ Name = "2" },
};
entries[0].Payroll = payrolls[0];
entries[1].Payroll = payrolls[0];
entries[2].Payroll = payrolls[1];
Payrolls.AddRange(payrolls);
Entries.AddRange(entries);
SaveChanges();
}
}
public class Payroll
{
public int PayrollId { get; set; }
public string Name { get; set; }
public List<Entries> Entries { get; set; }
}
public class Entries
{
public int EntryId { get; set; }
public string Name { get; set; }
public int? PayrollId { get; set; }
public virtual Payroll Payroll { get; set; }
}
Take a look at the Seed method above, no ids there due to database is fresh and empty.
internal class Program
{
static void Main(string[] args)
{
using (var _dbContext = new ApplicationContext())
{
_dbContext.Seed();
var entries = _dbContext.Entries
.Select(x => new {Id = x.EntryId, Name = x.Name, PayrollId = x.PayrollId})
.ToList();
var payrolls = _dbContext.Payrolls
.Select(x => new {Id = x.PayrollId, Name = x.Name})
.ToList();
Debug.WriteLine(JsonSerializer.Serialize(entries));
Debug.WriteLine(JsonSerializer.Serialize(payrolls));
}
}
}
Output will be
[
{"Id":1,"Name":"e1","PayrollId":1},
{"Id":2,"Name":"e2","PayrollId":1},
{"Id":3,"Name":"e3","PayrollId":2}
]
[
{"Id":1,"Name":"1"},{"Id":2,"Name":"2"}
]
Reference: https://docs.microsoft.com/en-us/ef/core/saving/related-data#adding-a-related-entity