✅ can't translate linq query
I have following query:
And got error:
I tried to add
AsEnumerable
after categories
and device.Categories
but it doesn't work24 Replies
What type is
device.Categories
?HashSet<string>
I'm not sure if every provider for EF supports collections of primitive types.
Without using a value converter that is
https://learn.microsoft.com/en-us/ef/core/modeling/relationships/one-to-many#required-one-to-many this is a good example on what your models would look like when implementing a one-to-many relationship
One-to-many relationships - EF Core
How to configure one-to-many relationships between entity types when using Entity Framework Core
I'm not sure but I imagine your own custom method
WhereCanRead()
can't be translated to sql. I have two ideas in mind what you can try out:
1. Try your custom WhereCanRead method on IEnumerable rather than IQueryable after materialising query with ToList(), so EF won't try to translate your thingy to sql because you do in memory on resulting enumerable.
2. I wonder why this WhereCanRead exists in the first place. Why not use the existing Where() method as you wish before materialising query rather than own custom WhereSomething() method? Then you can do this before materialising without worrying about Translation.
Take this with a grain of salt, I'm not sure if I understod the problem correctly
can you share the definition of that method pls?Might wanna read the error message a second time. It says that EF is unable to translate his where clause.
yep, a where clause with
category => ...
which I don't see here
I assume this might be the content of WhereCanRead
oh no its actualy the Any(device.Categories.Contains)
, I misunderstood it.hm, WhereCanRead actually works good
the problem is here:
let's try not to use single query:
and we will get the result, everything is correct!
so let's combine rows:
and now we got error:
also we can rewrite this a little bit: new error:
also we can rewrite this a little bit: new error:
Your top query works because the second
Where
clause never touches the DB.
var allCategories = dbContext.Set<Model.Entities.Device>().ToList();
fetches every device from the DB, then using normal linq to filter categories below it.ok I want this
I have
IEnumerable<string>
of categories
all I want is to take from the database those objects whose fields contain the necessary categoriesAnd what does your schema look like? Do you have a proper one-to-many relationship configured for device => categories?
Because what I've seen so far leads me to think you're storing all categories in a column on the
device
table as a single stringone moment
I can show Entity
I'm talking about your actual database schema, not the models you have in EF
jsonb
This a postgres db?
not that it makes much difference
but you should really move all categories out of that json blob and into their own table if you want them to be queryable.
which takes us back to my original suggestion on configuring a proper one-to-many relationship in your database
I don't think so
one moment
I know it is string but I don't even need another table for searching by DeviceSignature
so why do I need another table just for categories
I don't understand ..
Well, I don't even see a column named
DeviceSignature
in the schema you posted, so I have no clue what data type you're comparing againstit is
EndpointSignature
in database schema and it is text
Which effectively gets translated to
WHERE EndpointSignature IN (...)
Not the same as what you're doing with the categories.
Storing all categories in a json blob just feels like a poorly designed database, and trying to run complex queries on that isn't going to be as performant as a schema with properly configured relationships (and keys).
Considering you're also checking for categories by name, you'd probably want the category names indexed as well, which isn't possible to do with a json blob.Maybe you can use
EF.Functions.JsonContains
?
The problem is to use multiple values, a hacky way would tested, fyi.I'd really encourage you to move
Categories
to its own table though. It will be a much better (and scalable) solution long term.
And then you can use normal EF queries instead of finding hacky workarounds.I've been playing around. I've created an extension: https://paste.mod.gg/gdnzgfzdlwea/0
Here you can do the following:
But yeah, of course a new table would be better.
thanks a lot for helping
+1