I have the following code for filtering my data:
public List<Customer> ShowCustomersForCurrentTemplate(PushTemplate pushTemplate)
{
string templateType = pushTemplate.TemplateType;
string timeType = pushTemplate.IntervalType;
DateTime clientStartDate = pushTemplate.ClientStartDateTime;
int eventOlderThan = pushTemplate.EventOlderThan;
int eventYoungerThan = pushTemplate.EventYoungerThan;
List<string> langs = pushTemplate.Messages?.Select(x => x.PushLang?.LangCode).ToList() ??
new List<string>();
List<string> packageIds = pushTemplate.PackageIds ?? new List<string>();
List<string> advertisers = pushTemplate.AdvertiserPushTemplates?.Select(x => x.Advertiser?.Name).ToList() ??
new List<string>();
string category = pushTemplate.Category?.Name;
DateTime eventOlderThanDate = DateTime.UtcNow;
DateTime eventYoungerThanDate = DateTime.UtcNow;
if (timeType == "days")
{
eventOlderThanDate = eventOlderThanDate.AddDays(0 - eventOlderThan);
eventYoungerThanDate = eventYoungerThanDate.AddDays(0 - eventYoungerThan);
}
else if (timeType == "minutes")
{
eventOlderThanDate = eventOlderThanDate.AddMinutes(0 - eventOlderThan);
eventYoungerThanDate = eventYoungerThanDate.AddMinutes(0 - eventYoungerThan);
}
var customers = _customerRepository.Customers
.Include(x => x.Application)
.ThenInclude(x => x.Advertiser)
.ThenInclude(x => x.Category)
.Include(x => x.CustomerEvents)
.Select(x => x);
// selection by category
customers = customers.Where(x => x.Application.Advertiser.Category.Name == category);
// selection by advertisers
customers = customers.Where(x => advertisers.Contains(x.Application.Advertiser.Name));
// selection by applications
customers = customers.Where(x => packageIds.Contains(x.Application.AppId));
// selection by locales
customers = customers.Where(x => langs.Contains(x.Locale));
if (templateType == "registration_and_not_deposit")
{
// selection by event type
customers = customers.Where(x => x.CustomerEvents
.Any(y => y.Customer.CreatedAt > clientStartDate && y.CreatedAt <= eventOlderThanDate &&
y.CreatedAt >= eventYoungerThanDate && y.EventType == "registration"));
// set of redundant events
var customersWithEventsForException =
customers.Where(x => x.CustomerEvents.Any(y => y.EventType == "deposit"));
// filter redundant events
customers = customers.Except(customersWithEventsForException);
}
else if (templateType == "opened_and_not_registration")
{
// отбор по типу события
customers = customers.Where(x => x.CustomerEvents
.Any(y => y.Customer.CreatedAt > clientStartDate && y.CreatedAt <= eventOlderThanDate &&
y.CreatedAt >= eventYoungerThanDate && y.EventType == "open"));
// selection be event
var customersWithEventsForException =
customers.Where(x => x.CustomerEvents.Any(y => y.EventType == "registration"));
// filter redundant events
customers = customers.Except(customersWithEventsForException);
}
// set of users who already had push
var alreadyHavePush = _pushRepository.Pushes
.Include(x => x.Customer)
.Where(x => x.PushTemplate.PushTemplateId == pushTemplate.PushTemplateId && x.Sent)
.Select(x => x.Customer);
// filter users, who already had push
var res = customers.Except(alreadyHavePush).Select(x => x).ToList();
return res;
}
Sorry for long method, but it's pretty simple. A make Where for IQueryable again and again then I use .ToList() for getting dinally filtered result.
Ok about the problem. It seems to me, that Except method gives me
System.ArgumentException: Expression of type 'System.Collections.Generic.IEnumerable1[Microsoft.EntityFrameworkCore.Query.Internal.AnonymousObject]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable1[System.Object]' of method 'System.Collections.Generic.IEnumerable1[System.Object] Except[Object](System.Collections.Generic.IEnumerable1[System.Object], System.Collections.Generic.IEnumerable`1[System.Object])'
I will show you this moment with debugger.
The first case. Here all is ok:
The second case:
I will not have kek2 because the described exception will be raised.
So what is wrong? It's impossible to use Except for IQuareable?
Here I will show the source code of customers repository:
public class CustomerRepository : ICustomerRepository
{
private readonly ApplicationDbContext _applicationContext;
public CustomerRepository(ApplicationDbContext applicationContext)
{
_applicationContext = applicationContext;
}
public IQueryable<Customer> Customers => _applicationContext.Customers;
...
Related
I have Linq which counts the goods, the problem is that the names that I pass, they do not work
ProductName, CompanyName, CustomerName,
Maybe there is a error in Linq?
It produces many anonymous methods that have these fields, but after ToList() everything does not work
public async Task<IEnumerable<SalesReportItem>> GetReportData(DateTime dateStart, DateTime dateEnd)
{
dateStart = new DateTime(2000, 1, 1);
var context = await _contextFactory.CreateDbContextAsync();
var queryable = context.SalesTransactionRecords.Join(
context.Products,
salesTransactionRecords => salesTransactionRecords.ProductId,
products => products.Id,
(salesTransactionRecords, products) =>
new
{
salesTransactionRecords,
products
})
.Join(context.Companies,
combinedEntry => combinedEntry.salesTransactionRecords.CompanyId,
company => company.Id,
(combinedEntry, company) => new
{
combinedEntry,
company
})
.Join(context.VendorCustomers,
combinedEntryAgain => combinedEntryAgain.combinedEntry.salesTransactionRecords.CustomerId,
vendorCustomer => vendorCustomer.Id,
(combinedEntryAgain, vendorCustomer) => new
{
CompanyName = combinedEntryAgain.company.Name,
CustomerName = vendorCustomer.Name,
ProductId = combinedEntryAgain.combinedEntry.products.Id,
ProductName = combinedEntryAgain.combinedEntry.products.Name,
combinedEntryAgain.combinedEntry.salesTransactionRecords.MovementType,
combinedEntryAgain.combinedEntry.salesTransactionRecords.Period,
combinedEntryAgain.combinedEntry.salesTransactionRecords.Quantity,
combinedEntryAgain.combinedEntry.salesTransactionRecords.Amount,
}).Where(x => x.Period >= dateStart && x.Period <= dateEnd)
.GroupBy(combinedEntryAgain => new
{
combinedEntryAgain.ProductId,
combinedEntryAgain.ProductName,
combinedEntryAgain.CompanyName,
combinedEntryAgain.CustomerName,
}
).Select(x => new SalesReportItem
{
ProductId = x.Key.ProductId,
Quantity = x.Sum(a => a.Quantity),
Amount = x.Sum(x => (x.MovementType == TableMovementType.Income ? x.Amount : -(x.Amount)))
});
var items = await queryable.ToListAsync();
return _mapper.Map<IEnumerable<SalesReportItem>>(items);
}
my mistake was that I did not specify the fields in the select, otherwise everything is buzzing, the upper code is working
Select(x => new SalesReportItem
{
ProductId = x.Key.ProductId,
ProductName = x.Key.ProductName,
CompanyName = x.Key.CompanyName,
CustomerName = x.Key.CustomerName,
Quantity = x.Sum(x => (x.MovementType == TableMovementType.Income ? x.Quantity : - x.Quantity)),
Amount = x.Sum(x => (x.MovementType == TableMovementType.Income? x.Amount: - x.Amount))
});
Thanks for the help
Hans Kesting
I'm trying to use the entity framework to filter my GET method... Using the if the condition it's working
public async Task<List<TimeEntryViewModel>> Get(TimeEntryFilter filter)
{
var result = await _readRepository
.FindByCondition(x => x.IsApproved == true)
.Include(x => x.Task)
.Include(x => x.Account)
.Select(x => new TimeEntryViewModel
{
AccountName = x.Account.Name,
Date = x.Date,
StartTime = x.StartTime,
FinishTime = x.FinishTime,
InternalId = x.InternalId,
TaskId = x.TaskId,
TaskName = x.Task.Name,
CreatedBy = x.CreatedBy,
CustomerName = x.Task.Project.ServiceOrder.Customer.Name
}).ToListAsync().ConfigureAwait(false);
if (filter.AccountName != null ||
(filter.StartDate.HasValue && filter.FinishDate.HasValue && (filter.StartDate <= filter.FinishDate)) ||
(filter.TaskName != null) ||
(filter.CustomerName != null) ||
(filter.InternalId != null))
result = result.Where(x =>
(x.AccountName.ToString().Contains(filter.AccountName)) &&
(x.Date >= filter.StartDate && x.Date <= filter.FinishDate) &&
(x.CustomerName.ToString().Contains(filter.CustomerName)) &&
(x.TaskName.ToString().Contains(filter.TaskName)) &&
(x.InternalId.ToString().Contains(filter.InternalId.ToString()))).ToList();
return result;
}
But I imagine that there is a way to improve this method without using if
I'd had already tried to do that (Just filter account name to show)
But returned Internal Server Error
var result = await _readRepository
.FindByCondition(x => x.IsApproved == true)
.Where(x => string.IsNullOrEmpty(filter.AccountName) || x.Account.Name.ToString().Contains(filter.AccountName))
.Include(x => x.Task)
.Include(x => x.Account)
.Select(x => new TimeEntryViewModel
{
Id = x.Id,
AccountName = x.Account.Name,
Date = x.Date,
Description = x.Description,
StartTime = x.StartTime,
FinishTime = x.FinishTime,
InternalId = x.InternalId,
OnSite = x.OnSite,
IsApproved = x.IsApproved,
IsBillable = x.IsBillable,
TaskId = x.TaskId,
TaskName = x.Task.Name,
CreatedBy = x.CreatedBy,
CustomerName = x.Task.Project.ServiceOrder.Customer.Name
}).ToListAsync().ConfigureAwait(false);
Okay Guys EDIT1: In my second sample, using InternalId instead of Account.Name
.Where(x => (string.IsNullOrEmpty(filter.InternalId.ToString())) || x.InternalId.ToString().Contains(filter.InternalId.ToString()))
it worked.... I believe that I'm having trouble to work with something that is a foreign key in my table...
There is a very interesting way to mass multiple bool values (contains or not etc) with only one value. It's called bit bitwise operations. Here: Most common C# bitwise operations on enums
you can find different approachs to this "technique".
It returned null because you don't check if Account property is null.
AccountName = x.Account.Name
So the above will throw a Null Reference Exception.
A way to avoid this, it is to use the null conditional operator:
AccountName = x.Account?.Name
You can follow the same approach also for properties like:
Task.Name
Task.Project.ServiceOrder.Customer.Name
And access them safely, by using the same operator, like below:
Task?.Name
Task?.Project?.ServiceOrder?.Customer?.Name
Based on the above you can follow the way you have already followed for AccountName property, but you have also at the same time to use the null conditional operator.
It looks like you need && operator:
.Where(x => string.IsNullOrEmpty(filter?.AccountName)
&& x?.Account?.Name.ToString().Contains(filter.AccountName))
because when you use || operator, then you can get NullReferenceException in the second part of your expression in Where:
x?.Account?.Name.ToString().Contains(filter.AccountName))
Okay, apparently, my problem was .Where(x => string.IsNullOrEmpty(filter.AccountName) || x.Account.Name.ToString().Contains(filter.AccountName)) after x.Account.Name I can't use ToString()... I don't know exactly why, but now works without the if condition
public async Task<List<TimeEntryViewModel>> GetApproved(TimeEntryFilter filter)
{
var result = await _readRepository
.FindByCondition(x => x.IsApproved == true)
.Include(x => x.Task)
.Include(x => x.Account)
.Where(x =>
(string.IsNullOrEmpty(filter.InternalId.ToString()) || x.InternalId.ToString().Contains(filter.InternalId.ToString())) &&
(string.IsNullOrEmpty(filter.AccountName) || x.Account.Name.Contains(filter.AccountName)) &&
(string.IsNullOrEmpty(filter.CustomerName) || x.Task.Project.ServiceOrder.Customer.Name.Contains(filter.CustomerName)) &&
(string.IsNullOrEmpty(filter.TaskName) || x.Task.Name.Contains(filter.TaskName)))
.Select(x => new TimeEntryViewModel
{
Id = x.Id,
AccountName = x.Account.Name,
Date = x.Date,
Description = x.Description,
StartTime = x.StartTime,
FinishTime = x.FinishTime,
InternalId = x.InternalId,
OnSite = x.OnSite,
IsApproved = x.IsApproved,
IsBillable = x.IsBillable,
TaskId = x.TaskId,
TaskName = x.Task.Name,
CreatedBy = x.CreatedBy,
CustomerName = x.Task.Project.ServiceOrder.Customer.Name
}).ToListAsync().ConfigureAwait(false);
return result;
}
If anyone knows why it's working, I'll be thankful
I migrate my old project to the new EF Core and found this problem
My old code:
private IQueryable<SeriesData> GetSeriesData(IQueryable<Series> query, long? userId = null)
{
DateTime date = DateTime.Today.AddMonths(1);
IQueryable<SeriesData> seriesDataQuery = query.Select(x => new SeriesData
{
Series = x,
Subscribed = userId.HasValue && x.Subscriptions.Any(y => y.UserId == userId),
CurrentSeasonNumber = x.Episodes.Where(z => z.ReleaseDate.HasValue && z.ReleaseDate < date).Max(y => y.SeasonNumber),
Channel = x.Channel,
Country = x.Channel.Country,
ReleaseGroups =
x.Episodes.SelectMany(z => z.Releases)
.Select(y => y.ReleaseGroup)
.Distinct() // 1
.OrderBy(y => y.Name) // 2
.Select(r => new ReleaseGroupData
{
ReleaseGroup = r,
Subscribed =
userId.HasValue &&
x.Subscriptions.Any(y => y.UserId == userId && y.ReleaseGroupId == r.Id)
}).ToList()
});
return seriesDataQuery;
}
When i execute this query i get "InvalidOperationException: Sequence contains more than one element" exception
But if i swap line 1 and 2 everything works.
I have the following method:
public IEnumerable<MyRosterDTO> MyRosterGetCustomers(
IEnumerable<Guid> SalesRepIds,
IEnumerable<Guid> escrowOfficerIds,
IEnumerable<int> targetTypes,
IEnumerable<int> tagIds,
IEnumerable<Guid> custTypes,
IEnumerable<int> distListIds,
bool myExceptions)
{
customerStatusLog cslAlias = null;
customer custAlias = null;
customerOptions coAlias = null;
employee salesRepAlias = null;
Office officeAlias = null;
ListTags tagsAlias = null;
MyRosterDTO dto = null;
contactInformation contactInfo = null;
var myRosterQuery = _sms.CurrentSession.QueryOver<customer>(() => custAlias)
.JoinAlias(c => c.CustomerOptions, () => coAlias)
.Left.JoinAlias(c => c.SalesRep, () => salesRepAlias)
.JoinAlias(c => coAlias.Company, () => officeAlias)
.Left.JoinAlias(c => c.ContactInfo, () => contactInfo)
.Where(x => contactInfo.ContactTypeID == 8);
#region Where Clauses for parameters
if (myExceptions)
{
myRosterQuery.Where(c => salesRepAlias.Id == _ctx.User.Id && _ctx.User.Id != officeAlias.RepId);
}
else
{
if (SalesRepIds != null)
{
if (SalesRepIds.Contains(Guid.Empty))
{
if (SalesRepIds.Count() > 1) { myRosterQuery.Where(c => salesRepAlias.Id.IsIn(SalesRepIds.ToArray()) || salesRepAlias.Id == null); }
else
{ myRosterQuery.Where(c => salesRepAlias.Id == null); }
}
else
{ myRosterQuery.Where(c => salesRepAlias.Id.IsIn(SalesRepIds.ToArray())); }
}
}
if (escrowOfficerIds != null
&& escrowOfficerIds.Any())
{
myRosterQuery.Where(c => coAlias.PreferredEscrowOfficer.IsIn(escrowOfficerIds.ToArray()));
}
if (targetTypes != null
&& targetTypes.Any())
{
myRosterQuery.JoinAlias(c => c.CustomerStatusLog, () => cslAlias)
.Where(() => cslAlias.StatusId.IsIn(targetTypes.ToArray()));
}
if (tagIds != null
&& tagIds.Any())
{
myRosterQuery.JoinAlias(c => c.Tags, () => tagsAlias)
.Where(() => tagsAlias.Id.IsIn(tagIds.ToArray()));
}
if (custTypes != null
&& custTypes.Any())
{
myRosterQuery.Where(c => coAlias.cusTypeID.IsIn(custTypes.ToArray()));
}
if (distListIds != null
&& distListIds.Any())
{
var distCustIds = _sms.CurrentSession.Query<ListofAgents>()
.Where(loa => distListIds.Contains(loa.ListId))
.Select(loa => loa.AgentId)
.Distinct();
myRosterQuery.Where(c => c.Id.IsIn(distCustIds.ToArray()));
}
#endregion
return myRosterQuery.SelectList(list => list
.SelectGroup(c => c.Id).WithAlias(() => dto.Id)
.SelectGroup(c => c.FirstName).WithAlias(() => dto.FirstName)
.SelectGroup(c => c.LastName).WithAlias(() => dto.LastName)
.SelectGroup(() => officeAlias.Name).WithAlias(() => dto.CompanyName)
.SelectGroup(() => officeAlias.Address1).WithAlias(() => dto.Address1)
.SelectGroup(() => officeAlias.Address2).WithAlias(() => dto.Address2)
.SelectGroup(() => officeAlias.City).WithAlias(() => dto.City)
.SelectGroup(() => officeAlias.State).WithAlias(() => dto.State)
.SelectGroup(() => officeAlias.Zip).WithAlias(() => dto.Zip)
.SelectGroup(() => contactInfo.ContactData).WithAlias(() => dto.Phone)
.SelectGroup(() => salesRepAlias.FirstName).WithAlias(() => dto.SalesRepFirstName)
.SelectGroup(() => salesRepAlias.LastName).WithAlias(() => dto.SalesRepLastName)
)
.TransformUsing(Transformers.AliasToBean<MyRosterDTO>())
.List<MyRosterDTO>();
}
The query is nice and fast, but the problem arises where if the record doesn't have a contactInfo with a ContactTypeID of 8, then that record gets tossed out of the final results. (8 equates to Phone Number, fyi.)
What I need to be able to do is get the customer record, show all the customers, but provide phone numbers where available, and nothing where it's not.
The trick is that the contactInfo contains multiple types of contact information (email, phone, fax, etc), and without the .Where clause above, the output data explodes, showing a record on the screen for each contactInfo record a user has - so a user with 3 contactInfo types in the DB shows as 3 rows of output data.
This method is used to get a list of customers based on the input parameters, but instead of showing customers who don't have phone numbers, along side those who do, I only get those who have them.
If this were SQL, I'd just have a nice
LEFT JOIN ContactInfo as CI on customer.UserId = CI.UserId AND CI.ContactTypeID = 8
and my resultant query would show customers both with and without phone numbers.
You need the "with clause", which comes from HQL and had been integrated in query over:
.Left.JoinAlias(c => c.ContactInfo, () => contactInfo, () => contactInfo.ContactTypeID == 8)
This produces following SQL:
SELECT ...
FROM
...
LEFT OUTER JOIN ContactInfo as CI on (customer.UserId = CI.UserId
AND CI.ContactTypeID = 8)
In contrast to
.Left.JoinAlias(c => c.ContactInfo, () => contactInfo)
.Where(x => contactInfo.ContactTypeID == 8)
Which creates
SELECT ...
FROM
...
LEFT OUTER JOIN ContactInfo as CI on (customer.UserId = CI.UserId)
WHERE CI.ContactTypeID = 8
WITH clause in HQL looks as following:
FROM
...
left join ContactInfo ci WITH ci.ContactTypeID = 8
See this blog post by Fabio.
I have function
public async Task<IQueryable<Document>> GetDocuments(...)
in which I search for documents under some given conditions. Some conditions can be skipped. At the end I perform union of these queries.
var documents = await documentService.GetDocuments(this, userId,
roleShowFullNumber, param.OrderColName(), param.SearchValue, filter);
var usersGroupsId = filter.UsersGroupsId;
if (usersGroupsId != null)
{
if (!usersGroupsId.Contains("All"))
{
IQueryable<Document> myDocs = Enumerable.Empty<Document>().AsQueryable();
if (usersGroupsId.Contains("myOrders"))
{
myDocs = documents.Where(x => x.OwnerId == userId || x.UserId == userId);
usersGroupsId = usersGroupsId.Where(x => x != "myOrders").ToArray();
}
IQueryable<Document> wards = Enumerable.Empty<Document>().AsQueryable();
if (usersGroupsId.Contains("wards"))
{
var relatedUserId = _db.Users.Where(x => x.Id == userId).Select(x => x.RelatedUserId).FirstOrDefault();
if (relatedUserId != null)
{
var myWards = _db.kh__Kontrahent.Where(x => x.kh_IdOpiekun == relatedUserId);
var myWardsUsers = _db.Users.Where(x => myWards.Any(w => w.kh_Id == (x.RelatedCustomerId == null ? -1 : x.RelatedCustomerId)));
wards = documents.Where(x => (myWardsUsers.Any(w => x.UserId == w.Id) || myWardsUsers.Any(w => x.OwnerId == w.Id)));
usersGroupsId = usersGroupsId.Where(x => x != "wards").ToArray();
}
}
IQueryable<Document> groups = Enumerable.Empty<Document>().AsQueryable();
if (usersGroupsId.Length > 0)
{
var usersGroups = _db.Groups.Where(x => usersGroupsId.Contains(x.Id.ToString()));
var usersList = usersGroups.Select(x => x.Users);
var users = usersList.SelectMany(x => x);
var usersId = users.Select(x => x.Id);
groups = _db.Documents.Where(x => (usersId.Any(u => u == x.OwnerId) || usersId.Any(u => u == x.UserId)));
}
documents = myDocs.Union(wards).Union(groups);
}
}
But if one of these partial queries is empty (was skipped) when I try obtain these documents in way shown below I got error.
var documentsPaginated = await documents.Skip(param.Start)
.Take(param.Length)
.ToListAsync();
Error: The source IQueryable doesn't implement IDbAsyncEnumerable.
How can I make this function to be able to skip some sub queries and then union all. I would prefer not to change function return value.
Try this, althought your code seems to have a massive amount of code smell...
public async Task<IQueryable<Document>> GetDocuments(...)
var documents = await documentService.GetDocuments(this, userId,
roleShowFullNumber, param.OrderColName(), param.SearchValue, filter);
var usersGroupsId = filter.UsersGroupsId;
if (usersGroupsId != null)
{
if (!usersGroupsId.Contains("All"))
{
IQueryable<Document> myDocs = null;
if (usersGroupsId.Contains("myOrders"))
{
myDocs = documents.Where(x => x.OwnerId == userId || x.UserId == userId);
usersGroupsId = usersGroupsId.Where(x => x != "myOrders").ToArray();
}
IQueryable<Document> wards = null;
if (usersGroupsId.Contains("wards"))
{
var relatedUserId = _db.Users.Where(x => x.Id == userId).Select(x => x.RelatedUserId).FirstOrDefault();
if (relatedUserId != null)
{
var myWards = _db.kh__Kontrahent.Where(x => x.kh_IdOpiekun == relatedUserId);
var myWardsUsers = _db.Users.Where(x => myWards.Any(w => w.kh_Id == (x.RelatedCustomerId == null ? -1 : x.RelatedCustomerId)));
wards = documents.Where(x => (myWardsUsers.Any(w => x.UserId == w.Id) || myWardsUsers.Any(w => x.OwnerId == w.Id)));
usersGroupsId = usersGroupsId.Where(x => x != "wards").ToArray();
}
}
IQueryable<Document> groups = null;
if (usersGroupsId.Length > 0)
{
var usersGroups = _db.Groups.Where(x => usersGroupsId.Contains(x.Id.ToString()));
var usersList = usersGroups.Select(x => x.Users);
var users = usersList.SelectMany(x => x);
var usersId = users.Select(x => x.Id);
groups = _db.Documents.Where(x => (usersId.Any(u => u == x.OwnerId) || usersId.Any(u => u == x.UserId)));
}
if(myDocs != null)
documents = documents.Union(myDocs);
if(wards != null)
documents = documents.Union(wards);
if(groups != null)
documents = documents.Union(groups);
}
}
It appears that ToListAsync can't be used interchangeably with linq, but only in an EF query.
Quote from MSDN
Entity Framework 6 introduced a set of extension methods that can be used to asynchronously execute a query. Examples of these methods include ToListAsync, FirstAsync, ForEachAsync, etc.
Because Entity Framework queries make use of LINQ, the extension methods are defined on IQueryable and IEnumerable. However, because they are only designed to be used with Entity Framework you may receive the following error if you try to use them on a LINQ query that isn’t an Entity Framework query.
The source IQueryable doesn't implement IDbAsyncEnumerable{0}. Only sources that implement IDbAsyncEnumerable can be used for Entity Framework asynchronous operations. For more details see http://go.microsoft.com/fwlink/?LinkId=287068.