EntityFrameworkCore.Projectables
EntityFrameworkCore.Projectables copied to clipboard
Overriden property not getting used
Hi I am having a base type and a few derived types of it.
[Table("JournalEntryRefs")]
public abstract class JournalEntryRef
{
[Projectable]
public virtual string? DisplayName => null;
}
[Table("JournalEntryRefs")]
public class InvoiceJournalEntryRef : JournalEntryRef
{
[Projectable]
public override string? DisplayName => Invoice.Number != null ? Invoice.Number : "";
}
[Table("JournalEntryRefs")]
public class PaymentJournalEntryRef : JournalEntryRef
{
[Projectable]
public override string? DisplayName => Payment.Number;
}
When I query all the JournalEntryRef's(ie a collection somewhere) I specify that I want the reference column(beside others) and I'd expect that as such it would return the Invoice number for Invoice JournalEntryRef and Payment number for PaymentEntryRef. But currently they are always null. Is that a bug? If so how can we fix it? Or is that entirely not possible?
Can you try and use methods instead of properties and see if the issue persists? We have done work to support calling derived projectable methods, I'm not sure if this work also translated to properties.
Looking forward to hearing back.
Can you try and use methods instead of properties and see if the issue persists? We have done work to support calling derived projectable methods, I'm not sure if this work also translated to properties.
Looking forward to hearing back.
Still the same
[Table("JournalEntryRefs")]
public abstract class JournalEntryRef
{
[Projectable]
public string? DisplayName => GetDisplayName();
[Projectable]
public virtual string? GetDisplayName() => null;
}
[Table("JournalEntryRefs")]
public class InvoiceJournalEntryRef : JournalEntryRef
{
[Projectable]
public override string? GetDisplayName() => Invoice.Number != null ? Invoice.Number : "";
}
[Table("JournalEntryRefs")]
public class PaymentJournalEntryRef : JournalEntryRef
{
[Projectable]
public override string? GetDisplayName() => Payment.Number;
}
[Table("JournalEntryRefs")]
public class BankEntryJournalEntryRef : JournalEntryRef
{
[Projectable]
public override string? GetDisplayName() => "BE";
}
Tho to be 100% exact Iam accessing it yet from another class(JournalEntries) as Projectable
[Projectable]
public string? Reference => JournalEntryRef != null ? JournalEntryRef.DisplayName : null;
EDIT: Here's the SQL when querying for all the Journal Entries, it seems the the if case is getting generated incorrectly.
SELECT `j`.`Id`, `j0`.`AccountNo`, `j0`.`CompanyId`, `j0`.`ActiveFrom`, `j0`.`ActiveTo`, `j0`.`CreatedAt`, `j0`.`DeletedAt`, `j0`.`Description`, `j0`.`Type`, `j0`.`UpdatedAt`, `j1`.`AccountNo`, `j1`.`CompanyId`, `j1`.`ActiveFrom`, `j1`.`ActiveTo`, `j1`.`CreatedAt`, `j1`.`DeletedAt`, `j1`.`Description`, `j1`.`Type`, `j1`.`UpdatedAt`, CASE
WHEN `j2`.`Id` IS NOT NULL THEN NULL
ELSE NULL
END, `j`.`Description`, `j`.`AccountReceivableNo`, `j`.`AccountPayableNo`, `j`.`Amount`, `j`.`Date`
FROM `JournalEntries` AS `j`
INNER JOIN `JournalAccounts` AS `j0` ON (`j`.`AccountReceivableNo` = `j0`.`AccountNo`) AND (`j`.`CompanyId` = `j0`.`CompanyId`)
INNER JOIN `JournalAccounts` AS `j1` ON (`j`.`AccountPayableNo` = `j1`.`AccountNo`) AND (`j`.`CompanyId` = `j1`.`CompanyId`)
LEFT JOIN `JournalEntryRefs` AS `j2` ON `j`.`Id` = `j2`.`JournalEntryId`
WHERE `j`.`CompanyId` = @__p_0
ORDER BY `j`.`Date` DESC
Tho to be 100% exact Iam accessing it yet from another class(JournalEntries) as Projectable
There is a problem, during the query compilation phase, we do not know what JournalEntryRef is except for that its JournalEntryRef. So the only sensible thing it can do is project JournalEntryRef.GetDisplayName. Only when the query executes can it resolve what JournalEntryRef actually is.
You'll have to come up with something creative in order to bind to the correct implementation during query execution, e.g.
public string? Reference => JournalEntryRef is InvoiceJournalEntryRef ? ((InvoiceJournalEntryRef)JournalEntryRef).GetDisplayName() : JournalEntryRef is PaymentJournalEntryRef ? ((PaymentJournalEntryRef )JournalEntryRef).GetDisplayName() : JournalEntryRef is BankEntryJournalEntryRef ? ((BankEntryJournalEntryRef )JournalEntryRef).GetDisplayName() : null;
Tho to be 100% exact Iam accessing it yet from another class(JournalEntries) as Projectable
There is a problem, during the query compilation phase, we do not know what JournalEntryRef is except for that its JournalEntryRef. So the only sensible thing it can do is project JournalEntryRef.GetDisplayName. Only when the query executes can it resolve what JournalEntryRef actually is.
You'll have to come up with something creative in order to bind to the correct implementation during query execution, e.g.
public string? Reference => JournalEntryRef is InvoiceJournalEntryRef ? ((InvoiceJournalEntryRef)JournalEntryRef).GetDisplayName() : JournalEntryRef is PaymentJournalEntryRef ? ((PaymentJournalEntryRef )JournalEntryRef).GetDisplayName() : JournalEntryRef is BankEntryJournalEntryRef ? ((BankEntryJournalEntryRef )JournalEntryRef).GetDisplayName() : null;
And can't exactly this be generated by Projectables? Ie: If we know it's virtual the actual implementation will looks thru what inherits this class and generates the ifs?
Ie: If we know it's virtual the actual implementation will looks thru what inherits this class and generates the ifs?
Technically, yes. However that is a big ask. This would need substantial design. Feel free to propose something but at the moment, this would not be supported :)
Ie: If we know it's virtual the actual implementation will looks thru what inherits this class and generates the ifs?
Technically, yes. However that is a big ask. This would need substantial design. Feel free to propose something but at the moment, this would not be supported :)
Ok, Ill look into it