Entity Framework 6: .Where and .Select that accept string parameters? - entity-framework

In “Programming Entity Framework”, 2nd edition by Julia Lerman, in chapter dedicated to Entity SQL, p. 115, we have the following example of using query builder method to do projection using EF 4.1 .Where and .Select with string parameters:
ObjectQuery<DbDataRecord> contacts = context.Contacts
.Where("it.FirstName='Robert'")
.Select("it.Title, it.FirstName, it.LastName");
I am using Entity Framework 6, .Net 4.6, VS 2015. The compiler complains that there are no .Where and .Select that accept string parameters, only lambdas. Is there any solution how to follow this book example?

The example appears to be about the old ObjectQuery API, which shouldn't really be used now. It's still possible to use it with EF6.x though, with something like the following:
ObjectContext objectContext = ((IObjectContextAdapter)conte).ObjectContext;
ObjectSet<DbDataRecord> objectSet = objectContext.CreateObjectSet<DbDataRecord>("DbDataRecords");
// Async version: var res0 = await objectSet.Where("it.FirstName='Robert'").ToListAsync();
var res0 = objectSet.Where("it.FirstName='Robert'").ToList();
That said, you really should use the lambda instead with the new DbContext API.

Related

How to call builtin SQL Linq functions in EF Core?

I have a query written with Linq and EF Core 6 and I would like to call the builtin function EOMONTH on a date column.
Something like:
_context.Pet
.Select(x => EOMONTH(x.birthDate))
.DoStuff()
.ToListAsync();
How can I actually get to call EOMONTH and any other builtin SQL function from Linq?
The EF Core documentation has a page that show function mappings between LINQ and SQL.
As of EF Core 6, it looks like EOMONTH isn't yet supported, but you can provide your own function mapping like this:
class MyContext : DbContext
{
[DbFunction(IsBuiltIn = true)]
public static DateTime EOMONTH(DateTime startDate)
=> throw new InvalidOperationException(
"Don't call EOMONTH directly. It must to be translated to SQL " +
"inside of a LINQ query.");
}
_context.Pet
.Select(x => MyContext.EOMONTH(x.birthDate));
Note, lots of different styles are supported by EF. For example, it could also be an instance method. Read the docs to find the best way that works for you.

Filtering non-generic DbSet with dynamically built Expression

Plot:
I have a class implemented as a facade around Entity Framework DB context. It developed to maintain backward compatibility, it mimics class with same public interface, but uses DTOs instead of EF entities.
Problem:
I have next method inside class described above. See code below:
public IQueryable<T> FindBy<T>(Expression<Func<T, Boolean>> predicate) where T : BaseDto {
//GetDestinationType takes source type of some declared mapping and returns destination type
var entityType = Mapping.Mapper.GetDestinationType(typeof (T));
var lambda = Expression.Lambda(predicate.Body, Expression.Parameter(entityType));
// dbContext declared as class field and initialized in constructor
var query = dbContext.Set(entityType).Where(lambda); // <-- Cannot use non-generic expression/lambda
return query.ProjectTo<T>(mapper.ConfigurationProvider); }
I need to take Expression using DTOs as In parameter and return IQueryable where T : BaseDto as a result
I need to convert input predicate to the same predicate using EF entities as In parameter
I need to filter non-generic EF DbSet with help of dynamically created Expression (predicate)
Main question
Is it possible to filter non-generic EF DBSet with help of dynamically created Expression (predicate)
Please give me some glue or further directions if I need to use some other approach.
Problem has been solved. Solution was quite obvious. Instead of
var query = dbContext.Set(entityType).Where(lambda);
I can write
var query = dbContext
.Set(entityType)
.ProjectTo<T>(mapper.ConfigurationProvider)
.Where(predicate);
where predicate is the input parameter of FindBy() method.
This code will be successfully compiled and, what is more important, EF will build optimal query to the Database which will include Where() clause in the query body, so it won't take full set of records from DB side.

Using CreateSourceQuery in LINQPad

How can I get linqpad to understand CreateSourceQuery in the following C# statements?
var airline = Airlines.FirstOrDefault(a => a.ID == 1776);
airline.Dump();
var crew = airline.Crew.CreateSourceQuery().Where(c => c.Title == "pilot");
crew.Dump();
Where Airlines.Crew is a navigation property. Linqpad gives the error:
'System.Data.Linq.EntitySet' does not contain a
definition for 'CreateSourceQuery' and no extension method
'CreateSourceQuery' accepting a first argument of type
'System.Data.Linq.EntitySet' could be found
Is this perhaps just a reference I need?
CreateSourceQuery is an Entity Framework method. LINQPad uses LINQ-2-SQL by default.
There's a walk-through on the LINQPad website which explains how to use it with Entity Framework:
http://www.linqpad.net/EntityFramework.aspx

IQueryable doesn't implement IDbAsyncEnumerable

The question was originally asked at http://entityframework.codeplex.com/discussions/399499#post928179 .
Good day! Please tell me if it is wrong place to post this question.
I have a query as follows:
IQueryable<Card> cardsQuery =
dataContext.Cards
.Where(predicate)
.OrderByDescending(kc => kc.SendDate)
.AsQueryable();
Then I try:
Task<Card[]> result = cardsQuery.ToArrayAsync();
And then exception rises:
The source IQueryable doesn't implement IDbAsyncEnumerable<Models.Card>
I use modified version of 'EF 5.x DbCotext generator'.
How to avoid it?
UPDATE
Important remark is that I have method to produce IQuerayble<Card> as follows:
class Repository {
public IQueryable<Card> GetKudosCards(Func<Card, bool> predicate) {
IEnumerable<KudosCard> kudosCards = kudosCardsQuery.Where(predicate);
return kudosCards
.OrderByDescending(kc => kc.SendDate)
.AsQueryable();
}
}
What is the point of calling AsQueryable? If you compose a query with the extension methods starting from an IQueryable source collection (e.g. DbSet, ObjectSet), the query will be IQueryable too.
The purpose of AsQueryable is to wrap an IEnumerable collection with an IQueryable proxy/adapter that uses a Linq provider that is capable of compiling IQueryable queries into a Linq to Object queries. This can be useful in scenarios when you would like to use inmemory data queries.
Why is the AsQueryable call necessary? What if you just simply remove it?
Update
Okey, now it seems I understand your problem. After a quick look on the ODataQueryOptions.ApplyTo I realized that it just extends the underlying expression tree of the query. You can still use it to run the query in the way you want, however you need a little trick to transform the query back to generic.
IQueryable<Card> cardsQuery =
dataContext.Cards
.Where(predicate)
.OrderByDescending(kc => kc.SendDate);
IQueryable odataQuery = queryOptions.ApplyTo(cardsQuery);
// The OData query option applier creates a non generic query, transform it back to generic
cardsQuery = cardsQuery.Provider.CreateQuery<Card>(odataQuery.Expression);
Task<Card[]> result = cardsQuery.ToArrayAsync();
The problem is as follows.
I have a method:
class Repository {
public IQueryable<Card> GetKudosCards(Func<Card, bool> predicate) {
IEnumerable<KudosCard> kudosCards = kudosCardsQuery.Where(predicate);
return kudosCards
.OrderByDescending(kc => kc.SendDate)
.AsQueryable();
}
}
The problem is that kudosCards has type IEnumerable<KudosCard>. That throws exception. If I change predicate type to Expression<Func<Card, bool> predicate then everything works just fine.
I had the same problem when I was using the LinqKit library expression builder, which in the end, was producing AsQueryable(), and very surprisingly it was happening for me from the XUnit Integration Tests call.
I was going wild about why the same problem wasn't happening when calling the same API endpoint via Swagger.
It turned out I had to do an elementary change.
I had to replace:
using System.Data.Entity;
with:
using Microsoft.EntityFrameworkCore;
I had the same problem when I was using the LinqKit library expression builder, which in the end, was producing AsQueryable().
And very surprisingly, it was happening for me from the XUnit Integration Tests call.
I was going wild about why the same problem wasn't happening when calling the same API endpoint via Swagger.
It turned out I had to do an elementary change.
I had to replace the:
using System.Data.Entity;
with:
using Microsoft.EntityFrameworkCore;
In the place where I was calling the LinqKit expression method.
If you want to use the List<T> for Linq query, Avoid chaining it with ToListAsync(). It uses the class IDbAsyncEnumerable that is not available to a normal List<T> object

ESQL in Entity Framework

Is there any good and, if possible, exhaustive documentation about ESQL in entity framework ?
I'm trying to make a select of an entity object with modification of a property using a method; something like this :
SELECT foo FROM context.foo WHERE foo.Price = AddTaxes(foo.Price)
There is msdn providing some documentation Entity SQL Language
You can also combine it with Linq2Entities with something like
context.foo
.Where("it.Price == #Price", new ObjectParameter[]
{ new ObjectParameter("Price", AddTaxes(price) } ).ToList()