I'm working in .Net Core 2.1, creating an application which uses multitenancy. I'm applying default filters to my context. However, Entity Framework is not properly leveraging parametrized queries.
I have a configuration options being passed to my context to apply constraints which look like so:
public class ContextAuthorizationOptions : DbAuthorizationOptions<AstootContext>
{
protected IUserAuthenticationManager _userManager;
protected int _userId => this._userManager.GetUserId();
public ContextAuthorizationOptions(IUserAuthenticationManager authenticationManager, IValidatorProvider validatorProvider)
: base(validatorProvider)
{
this._userManager = authenticationManager;
ConstraintOptions.SetConstraint<Message>(x => x.Conversation.ConversationSubscriptions
.Select(cs => cs.UserId)
.Any(userId => userId == this._userId));
}
}
As you can see my query uses a property to store the userId value. My context takes in the constraint options ad applies them OnModels creating like so:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var constraintOptions = this._authorizationOptions.ConstraintOptions;
constraintOptions.ApplyStaticConstraint(modelBuilder);
base.OnModelCreating(modelBuilder);
}
My Model options look like so:
protected List<Action<ModelBuilder>> _constraints = new List<Action<ModelBuilder>>();
public void SetConstraint<T>(Expression<Func<T, bool>> constraint)
where T: class
{
this._constraints.Add(m => m.Entity<T>().HasQueryFilter(constraint));
}
public void ApplyStaticConstraint(ModelBuilder modelBuilder)
{
foreach(var applyConstraint in this._constraints)
{
applyConstraint(modelBuilder);
}
}
Since my filters are using properties I would expect this to generate a parameterized query yet when dumping to messages table to list it generates this SQL
SELECT [x].[Id], [x].[ConversationId], [x].[Created], [x].[MessageText], [x].[SenderUserId]
FROM [Messages] AS [x]
INNER JOIN [Conversations] AS [x.Conversation] ON [x].[ConversationId] = [x.Conversation].[Id]
WHERE EXISTS (
SELECT 1
FROM [ConversationSubscriptions] AS [cs]
WHERE ([cs].[UserId] = 2005) AND ([x.Conversation].[Id] = [cs].[ConversationId]))
How can I modify my implementation so Entity Framework Core can leverage query caching?