Description
Moved from discussion #22162
Question
From @andrejohansson
I have a set of entities, whom all fulfill an interface IOwnedEntity
public interface IOwnedEntity
{
BookingSupplier Owner { get; set; }
}
These entities get a query filter applied to them:
builder.HasQueryFilter(x => this.UserContext.OwnedBookingSuppliers.Contains(x.Owner.Id));
This filter works well with about 60 different entities, except for one entity: Rule
, when retrieving this entity I get the exception:
The LINQ expression 'DbSet<Rule>\r\n .Where(r => __ef_filter__OwnedBookingSuppliers_1\r\n .Contains(r.Owner.Id))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information
I am wondering what is different with this entity that causes it not being able to evaluate the query server side since it´s a fairly simple query?
I am guessing that it is the fact that Rule is an abstract base class for a set of other entities that inherits Rule. In the modelbuilder I have no special configuration for Rule but there is configurations for descendants that look like this:
modelBuilder.Entity<CompositeRule>()
.HasOne(p => p.Owner)
.WithMany(p => p.OwnedCompositeRules)
.OnDelete(DeleteBehavior.NoAction);
Relevant parts of rule:
public abstract class Rule : BaseEntity, IRule, IOwnedEntity
{
[Required] public virtual BookingSupplier Owner { get; set; }
public Guid? BookingSupplierOwnerId { get; set; }
/// ...
}
A class referencing rules can look like this:
public class ServiceArticle :
OwnedEntity,
IUserModifyableEntity,
IRulable<ServiceTranslation>
{
public virtual List<Rule> Rules { get; set; }
/// ...
}
Does anybody know the cause? or can anybody give me hints on how to debug this so that I can learn why it´s failing to translate?
Replies
From @smitpatel
Can you share a stand-alone repro?
From @ajcvickers
@smitpatel Based on this:
I am guessing that it is the fact that Rule is an abstract base class for a set of other entities that inherits Rule. In the modelbuilder I have no special configuration for Rule but there is configurations for descendants that look like this:
I'm guessing that Rule is an unmapped base type. Would this explain what is being seen?
From @smitpatel
r.Owner.Id seems to not getting expanded. My guess is r.Owner navigation is not getting expanded.
About not being mapped - There is DbSet in expression tree which comes from UserContext.OwnedBookingSuppliers means there is some DbSet. Plus, CompositeRule is in the model and a collection navigation property of Rules. Not sure if Rule is unmapped. But I could not create a runnable code based on pieces here.
From @andrejohansson
Managed to get this to work, but the error threw me of a bit. I had made two errrors:
- The latest migration contained a small, but significant change to the table. Preventing null from the owner relation
- My table contained null values (since they were previously allowed)
Once I fixed these things worked out for me.