Closed flensrocker closed 2 years ago
if (typeof(BaseDetailEntity<TCompanyEntity>).IsAssignableFrom(queryable.ElementType))
in WhereCompany
doesn't work either.
@flensrocker - There is nothing wrong with AsNoTracking
if you use any linq operator you will get the same result. If you replace AsNoTracking
with Skip(1)
above, you still get exception.
Here is the documentation of Skip
-> https://msdn.microsoft.com/en-us/library/bb358985(v=vs.110).aspx
All linq operators are defined as template method like Skip<TSource>
therefore compiler infer the type based on the type of source enumerator.
As long as you have DbSet you will have actual type of DbSet but once you apply any linq operator (or extension defined by EF like AsNoTracking) the type of the expression tree is changed to Enumerable<TSource>
since the variable is defined as IQueryable<BaseEntity>
TSource takes value BaseEntity
.
In first iteration, during WhereCompany
you are returning queryable itself so the type will be same as before applying where.
In second iteration, for first pass, you are casting type of queryable in your function before applying where so the type after where clause is the casted type. In the absence of that casting, Where would also return BaseEntity
only.
There is nothing on EF side to be done here.
Thank you, I think, I understand now.
I now have a solution with an interface with a non-generic function, which returns an IQueryable<BaseEntity>
, which is backed with two generic implementations for the different entity-types (BaseCompanyEntity
and BaseDetailEntity
).
Storing a
DbSet<DerivedClass>
in anIQueryable<BaseClass>
typed property and later callingAsNoTracking()
on the stored queryable, the resulting query has anElementType
ofBaseClass
.Background:
I have several applications, which store data about companies. Each user belongs to exactly one company. These users should only see the entities which belongs to the same company. This is solved with one master entity (the company) and several company data entities ("DetailEntity" in the example) and a claim, which contains the company-id.
If a user is an administrator, this user has no claim with a company-id and therefor should only see entities, which don't belong to companies (e.g. the company-entity itself). The administrator should only create/edit/delete companies, any other data is handled by the users of the companies.
I have library containing some general logic and base classes for these entities etc. It also provides some extensions for filtering the entities. These are used for dynamic forms generated at runtime for creating/editing data inside the company.
The application manages a list of the entities, where the lib should generate dynamic forms. As a guard for errors in configuration by the developer (besides the unit-tests of course), we have a filter, which checks if the accessed entity has an company-Id and the user, which accesses this entity, has the claim with an company-id (or if both are missing). If they don't match, an exception is thrown, so nobody should access data, which he shouldn't see (with a runtime-generated form).
The example reflects the structure of the lib and an application.
What am I doing wrong?
Steps to reproduce
Just do
dotnet restore
anddotnet run
.project.json
Program.cs
Further technical details
EF Core version: 1.1.0 Database Provider: Microsoft.EntityFrameworkCore.SqlServer Operating system: Windows 10 64 Bit IDE: dotnet