LinqToDb fails with "Association key not found for type"
See original GitHub issueTrying to use linq2db with existing EF code base and found a case, which might be interesting to you as it seems to be valid for EF, but will fail in runtime when linq2db is used as expression engine.
Let’s say we have next domain model:
public class Container
{
public int Id { get; set; }
public virtual ICollection<Item> Items { get; set; }
public virtual ICollection<ChildItem> ChildItems { get; set; }
}
public class Item
{
public int Id { get; set; }
public int ContainerId { get; set; }
public virtual ChildItem Child { get; set; }
public virtual Container Container { get; set; }
}
public class ChildItem
{
public int Id { get; set; }
public virtual Item Parent { get; set; }
}
ChildItem
here is basically a descendant of Item
, but relationship is implemented with use of composition instead of inheritance (migrating from EF 6 to EF Core 3, which doesn’t support Table Per Type for hierarchies, hence such design).
And of course in real-world model both Item
and ChildItem
have more attributes and there’re multiple Item
“descendants” omitted here for brevity.
Configuration for these entities is as follows:
internal sealed class ContainerConfiguration : IEntityTypeConfiguration<Container>
{
public void Configure(EntityTypeBuilder<Container> _)
{
_.HasKey(x => x.Id);
_.Property(x => x.Id).UseIdentityColumn();
}
}
internal sealed class ItemConfiguration : IEntityTypeConfiguration<Item>
{
public void Configure(EntityTypeBuilder<Item> _)
{
_.HasKey(x => x.Id);
_.Property(x => x.Id).UseIdentityColumn();
_.HasOne(a => a.Container)
.WithMany(b => b.Items)
.IsRequired()
.HasForeignKey(a => a.ContainerId);
}
}
internal sealed class ChildItemConfiguration : IEntityTypeConfiguration<ChildItem>
{
public void Configure(EntityTypeBuilder<ChildItem> _)
{
_.HasKey(e => e.Id);
_.Property(e => e.Id).ValueGeneratedNever();
// semantically each ChildItem is also an Item, hence one-to-one relationship with Id as FK
_.HasOne(a => a.Parent)
.WithOne(b => b.Child)
.IsRequired()
.HasForeignKey<ChildItem>(a => a.Id);
}
}
Then this query, which is pretty valid in terms of EF will fail (EF 6 was able to handle that, but EF Core fails as well due to a known bug). Error message is Association key 'ContainerId' not found for type 'ChildItem.
var children =
dbContext.Containers
.Select(c => new
{
ChildItems = c.ChildItems
.Select(ch => new
{
ContainerId = ch.Parent.ContainerId,
}),
})
.ToLinqToDB()
.ToArray();
Things work, if I rewrite my query this way, using Items
as an entry point and navigating to child in the expression instead of using ChildItems
directly.
var children =
dbContext.Containers
.Select(c => new
{
ChildItems = c.Items
.Select(i => i.ChildItem)
.Select(ch => new
{
ContainerId = ch.Parent.ContainerId,
}),
})
.ToLinqToDB()
.ToArray();
Having said that, do I get it correctly that it’s not possible to have ChildItems
collection inside the Container
type with linq2db?
Here is a code, if you decide to check it out to improve sth in the libraries. Repro.zip
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:7 (1 by maintainers)
Top GitHub Comments
This issue is not only present in some exotic table setup. I ran into the same with the simplest possible many-to-one relation between two tables, and managed to replicate it in Microsoft’s OData BookStore demo project (slightly modified to use SQLExpress instead of in-memory).
Basically, a query like this
will give the following error
Seems like a bug to me. Or am I not using
ToLinqToDB()
correctly?Here’s the project: BookStoreDotNet5.zip
Have found the same behaviour in a 1…* with the child expecting a reference to the parent, using an explicit [ParentName]Id. I’m just trying to use the TempTable as part of EF Core. EF Core can handle the relationship implicitly and I don’t want to start spreading [ParentName]Id in all my model files. It’s really a shame as otherwise it very much fitted my requirements.