First I will expose the code that reproduces the problem. Then I will explain the problem.
I have two entities, Employee and ContactForm (address, email, telephone...):
public class Employee
{
public long Id { get; set; }
public string UserName { get; set; }
public ObservableCollection<ContactForm> Telephones { get; set; } = new ObservableCollection<ContactForm>();
public ObservableCollection<ContactForm> Emails { get; set; } = new ObservableCollection<ContactForm>();
}
public class ContactForm
{
public long Id { get; set; }
public string Contact { get; set; }
}
This is the fluent API configuration of Employee:
public class EmployeeConfiguration : IEntityTypeConfiguration<Employee>
{
public void Configure(EntityTypeBuilder<Employee> paramEmployeefiguracion)
{
paramEmployeefiguracion.ToTable("Employees");
paramEmployeefiguracion.HasKey(o => o.Id);
paramEmployeefiguracion.Property<long>(o => o.Id)
.HasColumnName("IDEmployee")
.HasColumnType("bigint")
.IsRequired();
paramEmployeefiguracion.Property<string>(o => o.UserName)
.HasColumnName("UserName")
.HasColumnType("varchar(500)")
.IsRequired();
paramEmployeefiguracion
.HasMany(x => x.Telephones)
.WithOne()
.HasForeignKey("IDEmployee");
paramEmployeefiguracion
.HasMany(x => x.Emails)
.WithOne()
.HasForeignKey("IDEmployee");
}
}
This is the fluent API configuration of ContactForms:
public class ContactsFormsConfiguration : IEntityTypeConfiguration<ContactForm>
{
public void Configure(EntityTypeBuilder<ContactForm> paramContactFormConfiguration)
{
paramContactFormConfiguration.ToTable("ContactsForms");
paramContactFormConfiguration.HasKey(o => o.Id);
paramContactFormConfiguration.Property<long>(o => o.Id)
.HasColumnName("IDContactForm")
.HasColumnType("bigint")
.IsRequired();
//SHADOW PROPERTY
paramContactFormConfiguration.Property<long>("IDContactFormType")
.HasColumnName("IDContactFormType")
.HasColumnType("bigint")
.IsRequired();
paramContactFormConfiguration.Property<string>(o => o.Contact)
.HasColumnName("ContactForm")
.HasColumnType("varchar(200)");
}
}
And this is the query:
public async Task<Employee?> GetEmployeeWithTelephonesAndEmails(long paramIdEmployee)
{
return await _context.Employees
.AsNoTracking()
.Include(x => x.Telephones.Where(y => EF.Property<long>(y, "IDContactFormType") == 2))
//.Include(x => x.Emails.Where(y => EF.Property<long>(y, "IDContactFormType") == 3))
.FirstOrDefaultAsync(x => x.Id == paramIdEmployee);
}
This are the two tables in my database:
- Employee(IDEmployee, UserName)
- ContactsForms(IDContactForm, ContactForm, IDEmployee, IDContactFormType)
- ContactsFormsTypes(IDContactFormType, Type)
Now, the problem.
The problem is that if in the Employee entity I use the two collections (telephones and emails), I get the error that the column name EmployeeId is not valid.
If for example, in Employee I comment the collection Emails, I comment the configuration in the configuration of the employee and I comment the include in the query, it works. I include the telephones.
But when I uncomment the Emails collection and want to include both, telephones and emails, I get the error.
This is the query that EF sends to the database:
SELECT [t].[IDEmployee], [t].[UserName], [t0].[IDContactForm], [t0].[ContactForm], [t0].[EmployeeId], [t0].[IDContactFormType], [t0].[IDEmployee], [t1].[IDContactForm], [t1].[ContactForm], [t1].[EmployeeId], [t1].[IDContactFormType], [t1].[IDEmployee]
FROM (
SELECT TOP(1) [e].[IDEmployee], [e].[UserName]
FROM [Employees] AS [e]
WHERE [e].[IDEmployee] = @__paramIdEmployee_0
) AS [t]
LEFT JOIN (
SELECT [c].[IDContactForm], [c].[ContactForm], [c].[EmployeeId], [c].[IDContactFormType], [c].[IDEmployee]
FROM [ContactsForms] AS [c]
WHERE [c].[IDContactFormType] = CAST(2 AS bigint)
) AS [t0] ON [t].[IDEmployee] = [t0].[EmployeeId]
LEFT JOIN (
SELECT [c0].[IDContactForm], [c0].[ContactForm], [c0].[EmployeeId], [c0].[IDContactFormType], [c0].[IDEmployee]
FROM [ContactsForms] AS [c0]
WHERE [c0].[IDContactFormType] = CAST(3 AS bigint)
) AS [t1] ON [t].[IDEmployee] = [t1].[IDEmployee]
ORDER BY [t].[IDEmployee], [t0].[IDContactForm]',N'@__paramIdEmployee_0 bigint',@__paramIdEmployee_0=1
As you can see, in the left join, it tries to use [c].[EmployeeId], where c0 is the table ContactsForms.
The query that is send when I comment the Emails collection, when the query works, is this:
SELECT [t].[IDEmployee], [t].[UserName], [t0].[IDContactForm], [t0].[ContactForm], [t0].[IDContactFormType], [t0].[IDEmployee]
FROM (
SELECT TOP(1) [e].[IDEmployee], [e].[UserName]
FROM [Employees] AS [e]
WHERE [e].[IDEmployee] = @__paramIdEmployee_0
) AS [t]
LEFT JOIN (
SELECT [c].[IDContactForm], [c].[ContactForm], [c].[IDContactFormType], [c].[IDEmployee]
FROM [ContactsForms] AS [c]
WHERE [c].[IDContactFormType] = CAST(2 AS bigint)
) AS [t0] ON [t].[IDEmployee] = [t0].[IDEmployee]
ORDER BY [t].[IDEmployee]',N'@__paramIdEmployee_0 bigint',@__paramIdEmployee_0=1
In this case, it uses [c].[IDEmployee] in the left join, so it is correct.
Thanks.