Following up on this question/answer
How to make Entity Framework Data Context Readonly
The solution is to make your DbContext collections of the type DbQuery, but that is a rather specialized type (it's buried down in the namespaces for EF).
So, what's the functional difference between have a DbContext with this:
public DbQuery<Customer> Customers
{
get { return Set<Customer>().AsNoTracking(); }
}
vs this:
public IQueryable<Customer> Customers
{
get { return Set<Customer>().AsNoTracking(); }
}
...the EF documentation is very light when it comes to the DbQuery class, but I prefer the idea of having DbContext made up of interfaces rather than classes so I'd like to avoid it. What additional benefits does the DbQuery class provide?
Update
After reading the answers and just looking at the code I realized my question was a little silly. I was too quick to ask before I thought! Obviously the underlying concrete object will be a DbQuery regardless, so the actually inner functionality will be the same. It seems to me that using IQueryable is the better choice. Thanks for your patience!
DBQuery is a non-generic LINQ to Entities query against a DbContext. Exposing this will give you LINQ functionality against Entities. If you don't need this, use the IQueryable
interface abstraction.
IOrderedQueryable
Intended for implementation by query providers. This interface represents the result of a sorting query that calls the method(s) OrderBy, OrderByDescending, ThenBy or ThenByDescending. When CreateQuery is called and passed an expression tree that represents a sorting query, the resulting IQueryable object must be of a type that implements IOrderedQueryable.
IListSource
Provides functionality to an object to return a list that can be bound to a data source.
IDbAsyncEnumerable
Asynchronous version of the IEnumerable interface that allows elements to be retrieved asynchronously. This interface is used to interact with Entity Framework queries and shouldn't be implemented by custom classes.
This is an old question, but it comes up in a google search on DbQuery, so just to update things a bit:
In EF Core 2.1, QueryTypes are now mapped to DbQuery types, as described in the documentation located at
https://docs.microsoft.com/en-us/ef/core/modeling/query-types
Here are the relevant bits:
Query types have many similarities with entity types...
...
However they are different from entity types in that they:
Do not require a key to be defined.
Are never tracked for changes on the DbContext and therefore are never inserted, updated or deleted on the database.
Are never discovered by convention.
- Only support a subset of navigation mapping capabilities - Specifically:
- They may never act as the principal end of a relationship.
- They can only contain reference navigation properties pointing to entities. Entities cannot contain navigation properties to query types.
Are addressed on the ModelBuilder using the Query method rather than the Entity method.
Are mapped on the DbContext through properties of type DbQuery rather than DbSet
Are mapped to database objects using the ToView method, rather than ToTable.
May be mapped to a defining query - A defining query is a secondary query declared in the model that acts a data source for a query type.
You define a QueryType in your DbContext like a DbSet, but using the DbQuery type:
public virtual DbQuery<CustomClassThatMapsYourQueryResults> QueryResults { get; set; }
Then in your OnModelCreating method you indicate that your custom results object is mapped to a stored proc in the database:
modelBuilder.Query<CustomClassThatMapsYourQueryResults>();
Then in your data access code somewhere:
var someVariable = 1;
var someOtherVariable = "someValue";
...
var myResults = _dbContext.FromSql($"spStoredProcName {someVariable} '{someOtherVariable}'");
As far as I know, the only way to populate the DbQuery< T > object is to use the FromSql() method. The DbQuery< T > results of the FromSql() method return IQueryable< T >.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With