我有一个贷款申请模型如下:
public class LoanApplication
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[DefaultSortable]
public int Id { get; set; }
[Required]
public Guid Identifier { get; set; }
public string OrganizationId { get; set; }
public string GlobalEmployeeId { get; set; }
public string Name { get; set; }
public DateTime? BirthDate { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string ResidentialAddress { get; set; }
public int EmployeeId { get; set; }
[ForeignKey("EmployeeId")]
public Employee Employee { get; set; }
}
它链接到数据库中已存在的员工类:
public class Employee
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[DefaultSortable]
public int Id { get; set; }
[Sortable]
public int? OrganizationId { get; set; }
[Searchable, Sortable]
public string FirstName { get; set; }
[Searchable, Sortable]
public string LastName { get; set; }
[Searchable, Sortable]
public string OtherNames { get; set; }
[Searchable, Sortable]
[Required]
public string EmployeeId { get; set; }
[Searchable, Sortable]
public string EmployeeNumber { get; set; }
[Sortable]
public string DepartmentId { get; set; }
[Sortable]
public string JobPositionId { get; set; }
[Sortable]
public string DivisionId { get; set; }
[Sortable]
public string UnitId { get; set; }
[Sortable]
public string PayBandId { get; set; }
[Sortable]
public string OrganisationLocationId { get; set; }
[Sortable]
[JsonConverter(typeof(StringEnumConverter))]
public EmployeePosition Position { get; set; }
[Sortable]
public bool Resident { get; set; } = true;
[Sortable]
public bool HasSecondaryEmployment { get; set; }
[Searchable, Sortable]
public string TIN { get; set; }
[Searchable, Sortable]
public string SocialSecurityNumber { get; set; }
public string NationalIdType { get; set; }
[Searchable, Sortable]
public string NationalIdNumber { get; set; }
[ForeignKey("OrganizationId")]
[IgnoreInJsonBackup]
public Organization Organization { get; set; }
[ForeignKey("PayScheduleId")]
[IgnoreInJsonBackup]
public PaySchedule PaySchedule { get; set; }
}
我注意到,在创建新的贷款申请时,贷款申请对象确实像预期的那样附加了employee对象。调用端点以创建贷款申请的示例响应返回新创建的贷款申请:
{
"id": 5,
"identifier": "e4cc7864-c18a-4e75-a7a1-8ab54e9a7fdc",
"organizationId": "1dd71d10-fac7-4f33-87df-679a9541bba1",
"globalEmployeeId": "a8185c5b-50ca-4bcf-a8a5-dd74b0c1ab6b-20191029141650",
"name": "Amal",
"birthDate": "1993-02-07T00:00:00",
"email": "email@email.com",
"phoneNumber": "818927999",
"residentialAddress": "nowhere",
"loanAmount": 300,
"purposeOfLoan": "to live",
"tenureUnit": "Month",
"tenureDuration": 6,
"employeeId": 139,
"employee": {
"id": 139,
"organizationId": 1,
"firstName": "Aladdin",
"lastName": "Acosta",
"otherNames": "Amal",
"gender": null,
"employeeId": "a8185c5b-50ca-4bcf-a8a5-dd74b0c1ab6b-20191029141650",
"employeeNumber": "EMP-0274",
"departmentId": "bee9a1a9-2c46-4611-ad78-55c55cbfb671",
"jobPositionId": "ebf362dc-0a73-48a7-b31b-d64bca31550c",
"divisionId": null,
"unitId": null,
"payBandId": null,
"organization": {
"id": 1,
"organizationId": "1dd71d10-fac7-4f33-87df-679a9541bba1",
"name": "Fair Cat",
"emailAddress": "fair@cat.com",
"country": "GH",
"state": null,
},
"paySchedule": null
}
}
但是在随后从数据库中获取它时,employee对象总是不存在,即使我像下面的示例查询那样使用Include:
var loanApplication = context.LoanApplications.Include(x => x.Employee).
FirstOrDefault(x => x.OrganizationId == organizationId &&
x.Identifier.ToString() == identifier);
从GET端点获取贷款申请时的响应示例。注意employee字段现在为空:
{
"id": 5,
"identifier": "e4cc7864-c18a-4e75-a7a1-8ab54e9a7fdc",
"organizationId": "1dd71d10-fac7-4f33-87df-679a9541bba1",
"globalEmployeeId": "a8185c5b-50ca-4bcf-a8a5-dd74b0c1ab6b-20191029141650",
"name": "Amal",
"birthDate": "1993-02-07T00:00:00",
"email": "email@email.com",
"phoneNumber": "818927999",
"residentialAddress": "nowhere",
"loanAmount": 300,
"purposeOfLoan": "to live",
"tenureUnit": "Month",
"tenureDuration": 6,
"employeeId": 139,
"employee": null
}
ETA:我拥有的其他具有类似链接的导航属性的现有模型也将这些导航属性设置为null,而它们以前工作正常,但我没有在这方面做任何更改。
ETA:根据请求添加了Db上下文类
public class AppDataContext : DbContext
{
public AppDataContext(DbContextOptions<AppDataContext> options)
: base(options)
{
this.Database.SetCommandTimeout(180);
Debug.WriteLine(DateTime.Now.ToString() + ": DB Context created on thread: " + Thread.CurrentThread.ManagedThreadId);
}
public virtual DbSet<Organization> Organizations { get; set; }
public virtual DbSet<OrganizationBankAccount> OrganizationBankAccounts { get; set; }
public virtual DbSet<Employee> Employees { get; set; }
public virtual DbSet<PayItem> PayItems { get; set; }
public virtual DbSet<PayStructure> PayStructures { get; set; }
public virtual DbSet<PayRun> PayRuns { get; set; }
public virtual DbSet<PayRunTask> PayRunTasks { get; set; }
public virtual DbSet<PayPeriod> PayPeriods { get; set; }
public virtual DbSet<EmployeePayRun> EmployeePayRuns { get; set; }
public virtual DbSet<ArchivedEmployeePayRun> ArchivedEmployeePayRuns { get; set; }
public virtual DbSet<PaySchedule> PaySchedules { get; set; }
public virtual DbSet<PayrollNotification> PayrollNotifications { get; set; }
public virtual DbSet<List> Lists { get; set; }
public virtual DbSet<OrganizationLocation> OrganizationLocations { get; set; }
public virtual DbSet<EmployeeHire> EmployeeHires { get; set; }
public virtual DbSet<EmployeeTermination> EmployeeTerminations { get; set; }
public virtual DbSet<InitialPayRun> InitialPayRuns { get; set; }
public virtual DbSet<RemittanceParty> RemittanceParties { get; set; }
public virtual DbSet<EmployeePayChange> EmployeePayChanges { get; set; }
public virtual DbSet<Account> Accounts { get; set; }
public virtual DbSet<MappingStructure> MappingStructures { get; set; }
public virtual DbSet<AccountMappingState> AccountMappingStates { get; set; }
public virtual DbSet<ContractorType> ContractorTypes { get; set; }
public virtual DbSet<PayRunAccountingPostingRecord> PayRunAccountingPostingRecords { get; set; }
public virtual DbSet<Jurisdiction> Jurisdictions { get; set; }
public virtual DbSet<JurisdictionScript> JurisdictionScripts { get; set; }
public virtual DbSet<TaxReliefType> TaxReliefTypes { get; set; }
public virtual DbSet<PayrollOnboarding> PayrollOnboardings { get; set; }
public virtual DbSet<PayItemTemplate> PayItemTemplates { get; set; }
public virtual DbSet<FixedPayItem> FixedPayItems { get; set; }
public virtual DbSet<PayrollEvent> Events { get; set; }
public virtual DbSet<JurisdictionDefault> JurisdictionDefaults { get; set; }
public virtual DbSet<PayrollToken> Tokens { get; set; }
public virtual DbSet<JobGrade> JobGrades { get; set; }
public virtual DbSet<PayGroup> PayGroups { get; set; }
public virtual DbSet<ApprovalScheme> ApprovalSchemes { get; set; }
public virtual DbSet<PayRunData> PayRunData { get; set; }
public virtual DbSet<DataUpdate> DataUpdates { get; set; }
public virtual DbSet<EmployeePayHistoryItem> EmployeePayHistory { get; set; }
public virtual DbSet<Holiday> Holidays{ get; set; }
public virtual DbSet<PaymentBatch> PaymentBatches { get; set; }
public virtual DbSet<PaymentRecord> PaymentRecords { get; set; }
public virtual DbSet<EmployeeSubscription> EmployeeSubscriptions { get; set; }
public virtual DbSet<SubscriptionEnrolment> SubscriptionEnrolments { get; set; }
public virtual DbSet<LoanApplication> LoanApplications { get; set; }
public virtual DbSet<BaseEmployeePayRun> BaseEmployeePayRuns { get; set; }
public virtual DbSet<PayRevision> PayRevisions { get; set; }
public virtual DbSet<SubscriptionProfile> SubscriptionProfiles { get; set; }
public virtual DbSet<PayRunSubscriptionAllocation> PayRunSubscriptionAllocations { get; set; }
public virtual DbSet<PaymentRecordSubscriptionAllocation> PaymentSubscriptionAllocations { get; set; }
public virtual DbSet<PayRunAllocatedPayment> PayRunPaymentAllocations { get; set; }
public virtual DbSet<PaymentRecordAllocatedPayment> PaymentRecordPaymentAllocations { get; set; }
//public virtual DbSet<XeroToken> XeroTokens { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Organization>().HasIndex(organization => organization.JurisdictionId).IsUnique(false);
modelBuilder.Entity<Organization>().Property(organization => organization.PayslipPasswordMethod)
.HasConversion(
v => v.ToString(),
v => (PayslipPasswordMethod) Enum.Parse(typeof(PayslipPasswordMethod), v)
);
modelBuilder.Entity<Employee>().HasIndex(employee => employee.OrganizationId).IsUnique(false);
modelBuilder.Entity<PayItem>().HasIndex(payItem => payItem.OrganizationId).IsUnique(false);
modelBuilder.Entity<PaySchedule>().HasIndex(paySchedule => paySchedule.OrganizationId).IsUnique(false);
modelBuilder.Entity<PayStructure>().HasIndex(payStructure => payStructure.OrganizationId).IsUnique(false);
modelBuilder.Entity<PayStructure>().HasIndex(payStructure =>payStructure.Scope).IsUnique(false);
modelBuilder.Entity<PayStructure>().HasIndex(payStructure => payStructure.OwnerId).IsUnique(false);
modelBuilder.Entity<PayRun>().HasIndex(payRun => payRun.PayScheduleId).IsUnique(false);
modelBuilder.Entity<PayRun>().HasIndex(payRun => payRun.DateCreated).IsUnique(false);
modelBuilder.Entity<PayRun>().HasIndex(payRun => payRun.Status).IsUnique(false);
modelBuilder.Entity<PayRun>().HasIndex(payRun => payRun.OrganizationId).IsUnique(false);
modelBuilder.Entity<PayRun>().HasIndex(payRun => payRun.DatePosted).IsUnique(false);
modelBuilder.Entity<PayPeriod>().HasIndex(payPeriod => payPeriod.PayScheduleId).IsUnique(false);
modelBuilder.Entity<PayPeriod>().HasIndex(payPeriod => payPeriod.PayRunPosted).IsUnique(false);
modelBuilder.Entity<EmployeePayRun>().HasIndex(employeePayRun => employeePayRun.PayRunId).IsUnique(false);
modelBuilder.Entity<EmployeePayRun>().HasIndex(employeePayRun => employeePayRun.DateGenerated).IsUnique(false);
modelBuilder.Entity<EmployeePayRun>().HasIndex(employeePayRun => employeePayRun.EmployeeId).IsUnique(false);
modelBuilder.Entity<EmployeePayRun>().HasIndex(employeePayRun => employeePayRun.Excluded).IsUnique(false);
modelBuilder.Entity<ArchivedEmployeePayRun>().HasIndex(archivedEmployeePayRun => archivedEmployeePayRun.PayRunId).IsUnique(false);
modelBuilder.Entity<ArchivedEmployeePayRun>().HasIndex(archivedEmployeePayRun => archivedEmployeePayRun.DateGenerated).IsUnique(false);
modelBuilder.Entity<ArchivedEmployeePayRun>().HasIndex(archivedEmployeePayRun => archivedEmployeePayRun.DateArchived).IsUnique(false);
modelBuilder.Entity<ArchivedEmployeePayRun>().HasIndex(archivedEmployeePayRun => archivedEmployeePayRun.EmployeeId).IsUnique(false);
modelBuilder.Entity<ArchivedEmployeePayRun>().HasIndex(archivedEmployeePayRun => archivedEmployeePayRun.Excluded).IsUnique(false);
modelBuilder.Entity<PayRunTask>().HasIndex(payRunTask => payRunTask.PayRunId).IsUnique(false);
modelBuilder.Entity<List>().HasIndex(list => list.OrganisationId).IsUnique(false);
modelBuilder.Entity<OrganizationBankAccount>().HasIndex(organizationBankAccount => organizationBankAccount.OrganizationId).IsUnique(false);
modelBuilder.Entity<PayrollNotification>().HasIndex(pn => pn.OrganizationId).IsUnique(false);
modelBuilder.Entity<FixedPayItem>().HasIndex(fixedPayItem => fixedPayItem.JurisdictionId).IsUnique(false);
modelBuilder.Entity<PayItemTemplate>().HasIndex(pit => pit.JurisdictionId).IsUnique(false);
modelBuilder.Entity<TaxReliefType>().HasIndex(tr => tr.JurisdictionId).IsUnique(false);
modelBuilder.Entity<PayrollEvent>().HasIndex(tr => tr.OrganizationId).IsUnique(false);
modelBuilder.Entity<EmployeeHire>().HasIndex(eh => eh.OrganizationId).IsUnique(false);
modelBuilder.Entity<EmployeeHire>().HasIndex(eh => eh.EmployeeId).IsUnique(false);
modelBuilder.Entity<EmployeeTermination>().HasIndex(et => et.OrganizationId).IsUnique(false);
modelBuilder.Entity<EmployeeTermination>().HasIndex(et => et.EmployeeId).IsUnique(false);
modelBuilder.Entity<InitialPayRun>().HasIndex(i => i.PayRunId).IsUnique(true);
modelBuilder.Entity<RemittanceParty>().HasIndex(r => r.OrganizationId).IsUnique(false);
modelBuilder.Entity<JurisdictionScript>().HasIndex(js => js.JurisdictionId).IsUnique(false);
modelBuilder.Entity<EmployeePayChange>().HasIndex(r => r.OrganizationId).IsUnique(false);
modelBuilder.Entity<JurisdictionDefault>().HasIndex(jd => jd.JurisdictionId).IsUnique(false);
modelBuilder.Entity<Account>().HasIndex(acc => acc.OrganizationId).IsUnique(false);
modelBuilder.Entity<MappingStructure>().HasIndex(ms => ms.OrganizationId).IsUnique(false);
modelBuilder.Entity<AccountMappingState>().HasIndex(ams => ams.PayRunId).IsUnique(false);
modelBuilder.Entity<ContractorType>().HasIndex(ct => ct.JurisdictionId).IsUnique(false);
modelBuilder.Entity<ContractorType>().HasIndex(ct => ct.OrganizationId).IsUnique(false);
modelBuilder.Entity<PayRunAccountingPostingRecord>().HasIndex(pr => pr.OrganizationId).IsUnique(false);
modelBuilder.Entity<PayItem>().HasIndex(payItem => new { payItem.Code, payItem.OrganizationId }).IsUnique(true);
modelBuilder.Entity<JobGrade>().HasIndex(j => j.OrganizationId).IsUnique(false);
modelBuilder.Entity<PayGroup>().HasIndex(pg => pg.OrganizationId).IsUnique(false);
modelBuilder.Entity<ApprovalScheme>().HasIndex(pg => pg.OrganizationId).IsUnique(true);
modelBuilder.Entity<PayRunData>().HasIndex(payRun => payRun.PayRunId).IsUnique(true);
modelBuilder.Entity<PayRunData>().HasIndex(payRun => payRun.OrganizationId).IsUnique(false);
modelBuilder.Entity<DataUpdate>().HasIndex(t => t.OrganizationId).IsUnique(false);
modelBuilder.Entity<EmployeePayHistoryItem>().HasIndex(x => x.OrganizationId).IsUnique(false);
modelBuilder.Entity<EmployeePayHistoryItem>().HasIndex(x => x.EmployeeId).IsUnique(false);
modelBuilder.Entity<Holiday>().HasIndex(e => e.Country).IsUnique(false);
modelBuilder.Entity<PaymentBatch>().HasIndex(x => x.PayRunId).IsUnique(false);
modelBuilder.Entity<PaymentBatch>().HasIndex(x => x.OrganizationId).IsUnique(false);
modelBuilder.Entity<PaymentRecord>().HasIndex(x => x.EmployeePayRunId).IsUnique(false);
modelBuilder.Entity<PaymentRecord>().HasIndex(x => x.PaymentBatchId).IsUnique(false);
modelBuilder.Entity<PaymentRecord>().HasIndex(x => x.PayRunIdentifier).IsUnique(false);
modelBuilder.Entity<EmployeeSubscription>().HasIndex(x => x.OrganizationId).IsUnique(false);
modelBuilder.Entity<EmployeeSubscription>().HasIndex(x => x.SubscriptionIdentifier).IsUnique(false);
modelBuilder.Entity<LoanApplication>().HasIndex(x => x.OrganizationId).IsUnique(false);
modelBuilder.Entity<SubscriptionEnrolment>().HasIndex(x => x.OrganizationId).IsUnique(false);
modelBuilder.Entity<BaseEmployeePayRun>(bepr =>
{
bepr.HasNoKey();
bepr.ToView("BaseEmployeePayRuns");
});
modelBuilder.Entity<PayRevision>(pr =>
{
pr.HasNoKey();
pr.ToView("PayRevisions");
});
modelBuilder.Entity<SubscriptionProfile>(pr =>
{
pr.HasNoKey();
pr.ToView("SubscriptionProfiles");
});
modelBuilder.Entity<PayRunSubscriptionAllocation>(spa =>
{
spa.HasNoKey();
spa.ToView("PayRunSubscriptionAllocations");
});
modelBuilder.Entity<PaymentRecordSubscriptionAllocation>(spa =>
{
spa.HasNoKey();
spa.ToView("PaymentSubscriptionAllocations");
});
modelBuilder.Entity<PayRunAllocatedPayment>(spa =>
{
spa.HasNoKey();
spa.ToView("PayRunPaymentAllocations");
});
modelBuilder.Entity<PaymentRecordAllocatedPayment>(spa =>
{
spa.HasNoKey();
spa.ToView("PaymentRecordPaymentAllocations");
});
}
}
ETA:生成的查询:
SELECT l."Id", l."ApprovedByIdentifier", l."ApprovedByName", l."BankAccountName", l."BankAccountNumber", l."BankName", l."BirthDate", l."CancelledByIdentifier", l."CancelledByName", l."DateApproved", l."DateCancelled", l."DateCreated", l."DateDeclined", l."DateUpdated", l."DeclinedByIdentifier", l."DeclinedByName", l."Email", l."EmployeeId", l."GHCardNumber", l."GHCard_Back", l."GHCard_Front", l."GlobalEmployeeId", l."Identifier", l."LoanAgreementForm", l."LoanAmount", l."Name", l."OrganizationId", l."PassportPicture", l."Payslip1", l."Payslip2", l."PhoneNumber", l."PurposeOfLoan", l."ResidentialAddress", l."Status", l."TenureDuration", l."TenureUnit", l.loan_application_comments
FROM "LoanApplications" AS l
WHERE (l."OrganizationId" = @__organizationId_0) AND (CAST(l."Identifier" AS text) = @__identifier_1)
LIMIT 1
- (请注意,此查询中的额外字段,如ApprovedByIdentifier等)不会出现在上面的类对象中,因为我只是将它们删除了,这样代码片段就不会太长)*
2条答案
按热度按时间mrzz3bfm1#
当我要求您提供DbContext类时,我怀疑关系没有完全配置。现在,我不完全确定这是导致问题的原因,但我认为值得一试。
在
DbContext
类中,完全配置关系:在
LoanApplication
中:在
Employee
中:我可能误解了关系,所以我会仔细检查,以确保关系是准确的。但话虽如此,一旦你有你的关系配置正确,我怀疑这将解决你的问题。
mdfafbf12#
我已经能够让它工作了,虽然我不知道为什么。我过去常常通过存储库类访问我所有的数据,而不是直接访问上下文。只是为了测试这是否是问题所在,我为贷款申请实现了一个repo类:
它基于这个基类(只有少数GET函数,但其他大多数只是CRUD的变体):
现在,我可以获得附加了雇员的贷款申请对象,并且生成的查询现在包括了一个连接,但我希望我能弄清楚为什么。