If this is a property implementation where Context is an Entity Framework DbContext and Tours is a DbSet...
public IQueryable ListQuery => Context.Tours;
... then the calling code has limited ability to continue the query. For example, I can't even call ToList() on the result.
How do I return an un-typed query, such that I can do things like Take and Skip on the result, without the calling code knowing what the type is?
I don't want the type to leak out of the interface, because then my data access code is tied to one EF model in particular.
I cast the result to IQueryable<object>. I'm not sure why that's allowable. Is it because its covariant?
Related
I'm looking for a way to intercept database queries as a means of getting some more in-depth performance stats. I'm after number of queries, query duration, the result data (for an idea of data magnitude) and ideally some access to any LINQ expression.
I can fall back on extending a base context class, creating another method to get DbSet, returning a wrapper there, but 1) that seems hackier than it ought to be, 2) any code there won't be able to distinguish getting cached results vs actual database accesses..
I've looked through the code and feel like wrapping ExecutionStrategyFactory or Database is the way to go - and while I can create an extension method on RelationalDbContextOptionsBuilder for the former, or /replace/ services, I can't see a way of wrapping either, such that the underlying provider's implementation is still used.
(See also: https://github.com/aspnet/EntityFramework/issues/6967)
Is there a decent place to hook into this?
For the ref of anyone else:
Ok, the trick is:
Replace the IRelationalConnection that EF Core's DI system uses via ReplaceService<IRelationalConnection, MyRc>(). Our new MyRc will wrap the existing connection to add hooks
In our MyRc, have a constructor param of IDatabaseProviderServices. The EF DI system will populate it. Cast that to IRelationalDatabaseProviderServices and then grab the RelationalConnection property from that
Wrap all methods, but have public DbConnection DbConnection { get; } return an instance of a DbConnection-wrapping class
In that wrapping class, have CreateDbCommand() return an instance of a DbCommand-wrapping class
In that wrapping class, have ExecuteDbDataReader() return an instance of a DbDataReader-wrapping class
Then, in the DbCommand and DbDataReader wrappers, we can see what commands and parameters are being sent to the database, and the results coming back.
This only works with relational models.
I'm not sure if there is a way to do this or if I should even be doing this at all. But I have a method that can be called on certain of my entities. But I want to write this method once to apply to all of the entities because I know they are similar in a certain way.
Is there a way to create an instance of an entity, at runtime, by referencing a string value of that entity type?
So my method would be GetSomething(Entity e)
and that can be called on 10 different entities.
at runtime I have a string "Entity4".
I want to create an instance of that entity and call the GetSomething() method on it.
Inside of GetSomething() I want to do:
using (var db = new TalonEF_test.GISTestProductionEntities())
{
List<runtimeEntity> es = db.runtimeEntity.Where(o => o.OB == oid).ToList();
}
"But I want to write this method once to apply to all of the entities because I know they are similar in a certain way."
Write an interface which defines this similarity and then have your entities implement it. When you need to refer to objects which could be any of the entities, use the interface. If you need to run concrete queries against EF, you can call GetType on your entity and use that in DbContext.Set<T> to get a DbSet reference to run queries against.
I have an "Investment" entity that is derived from "BaseEntity".
With _container.BaseEntities.OfType<Investment>() I get an ObjectQuery that always queries the database.
Therefore I would rather have an ObjectSet<Investment>.
I can't understand why EF doesn't support this for derived entities... Or does it? ;)
If I would go ahead and create a "root entity" in EF (which would be silly) that has associations to all my derived entities, I would get EntityCollections for those entities through the navigation properties of that one root-entity. But there must be another way...
Cheers
That is how it works in EF ObjectContext API. If you try to create ObjectSet for derived entity you will get:
ArgumentException: There are no
EntitySets defined for the specified
entity type 'Investment'. If
'Investment' is a derived type, use
the base type instead. Parameter name:
TEntity
Also once you define inheritance there are no navigation properties to derived entities. The association which offers navigation property is changed to inheritance.
I also followed your former questions which is probably source of this one and I have to say I tried a lot but I can never get your behavior. Even if I call Count directly to ObjectSet I always get SQL query (checked in the profiler) and count of entities in the database - not in the set.
ObjectQuery<T> does not always query the database. It is only a query specification - in this case a specification to return all BaseEntities of type Investment. You can compose it with additional filters or orderby clauses or projections and so on. Nothing is executed in the database until you apply some greedy operator like ToList() or First() etc. or until you apply a foreach loop to fetch the results.
I have been reading when using LINQ to entites a query is of type IQueryable before it is processed but when the query has been processed, it's no longer an IQueryable, but an ObjectQuery.
In that case, is it correct to write methods from my layer (repository layer) to return IQueryable?
Do I need to cast?
Why would I want to return an ObjectQuery?
I'm coming from a LINQ to SQL background where things were always IQueryable but EF seems to have changed this.
Any help really appreciated.
My repositories always returns IQueryable. The reason for this is that IQueryable is not dependent on EF whereas ObjectQuery is. So if I want my other layers to be persistance ignorant I don't want to introduce dependency on ObjectQuery.
ObjectQuery is implementation of IQueryable with several additional features. First feature you will quickly discover is Include function which is need for eager loading of navigation properties (related entities). Second feature is EQL - entity query language. EQL is second way how you can query your conceptual model. It has similar syntax as SQL. You can write simple query as string, pass it to ObjectQuery constructor and execute query or use it in Linq-To-Entities.
Is it possible to get a collection (Dictionary) out of an Entity Object? I need this in order to pass parts of the Properties of the object to a function that needs an IDictionary.
Use:
Context.EntitySetName.AsEnumerable().ToDictionary(o => o.Key, o => o.Value);
Some detail on this:
ToDictionary is not supported in LINQ to Entities. This means that LINQ query string containing ToDictionary will compile, but will not execute, because the Entity Framework does not know how to translate them into SQL. Therefore, you have to execute the query on the database server first. So you have to project your set into a list first, which enumerates the entity set. AsEnumerable will do that. Obviously, if the entity set is large, you probably don't want to do this with the whole thing. Use a Where call or a LINQ query to reduce the result set to only the items you want in the dictionary first.
I don't think I fully understand your question. I don't know of any way of binding your database tables to IDictionary properties if that is what you are referring to, but you should be able to create whatever properties or methods you need to build a dictionary, and pass that. Is writing a business object method not an option for some reason?