How to filter and include children using Z.EntityFramework - entity-framework

The query below is using Z.EntityFramework.Plus.EF6 to filter children. Its filtering and including the AssetXref entity correctly however the result is not able to include Child.Parent entity relationship
var result = await _repository.GetQuery<Assets>()
.IncludeFilter(x => x.AssetsXRef
.Where(y => y.Child.Perent.ParentID == parentID)
.Select(y => y.Child.Perent)
)
.Where(x => x.Active == true)
.ToListAsync();
I have also tried
var result = await _repository.GetQuery<Assets>()
.IncludeFilter(x => x.AssetsXRef
.Where(y => y.Child.Perent.ParentID == parentID)
)
.Include(x=>x.AssetsXRef.Select(y=>y.Child.Parent))
.Where(x => x.Active == true)
.ToListAsync();

The IncludeFilter is not compatible with Include. You need to use IncludeFilter all the way even if there is no filter
In addition, you need to always use the full parent filter on child
Here is an example:
var result = await _repository.GetQuery<Assets>()
.IncludeFilter(x => x.AssetsXRef.Where(y => y.Child.Perent.ParentID == parentID))
// Might be SelectMany
.IncludeFilter(x => x.AssetsXRef.Where(y => y.Child.Perent.ParentID == parentID).Select(y=>y.Child.Parent))
.Where(x => x.Active == true)
.ToListAsync();

Related

Entity Framework not including children in join

I am using inner join to return results with Entity Framework (v6.2.0) and the following code is not returning the RouteWaypoints children (i.e. route.RouteWaypoints is always null). Interestingly, single children are loading (Customer, OriginLocation, etc), but not multiple children:
public List<Route> GetAllForTripWithWaypoints(int tripId)
{
return (
from route in GetAllBaseWithWaypoints()
from tripTask in DbContext.TripTasks.Where(x =>
x.TripId == tripId && x.OriginLocationId == route.OriginLocationId)
select route
).ToList();
}
private IQueryable<Route> GetAllBaseWithWaypoints()
{
return DbContext.Routes
.Include(x => x.Customer)
.Include(x => x.OriginLocation)
.Include(x => x.DestinationLocation)
.Include(x => x.RouteWaypoints.Select(y => y.Location))
.OrderBy(x => x.OriginLocation.Name).ThenBy(x => x.DestinationLocation.Name)
.AsQueryable();
}
This approach does work if I load just the Route entity, but not when I do the join. As a reference, this does load the children successfully:
public Route GetByIdWithWaypoints(int id, bool validateExists = true)
{
var route = GetAllBaseWithWaypoints().FirstOrDefault(x => x.Id == id);
if (validateExists && route == null)
throw new Exception("Route not found for id: " + id);
return route;
}
How can I keep it working when joining?
I did an imperfect workaround by making two calls to the db - slightly less efficient, but it solves the problem:
public List<Route> GetAllForTripWithWaypoints(int tripId)
{
var routeIds = (
from route in GetAllBase()
from tripTask in DbContext.TripTasks.Where(x =>
x.TripId == tripId && x.OriginLocationId == route.OriginLocationId)
select route.Id
).ToList();
return GetAllBaseWithWaypoints().Where(x => routeIds.Contains(x.Id)).ToList();
}

Get all the roles after include with main entity in Entity framework Core

I have three entities which are Account, Role and AccountRole. Through repository pattern I have fetched all the accounts, roles and accountRoles like below:
var accounts = _accountRepository.Query()
.Include(x => x.AccountRoles)
.ThenInclude(x => x.Role);
Now I would like to get a single account information with all it's roles. So I have written the below query. But the problem is only first role comes out.
var userAccount = accounts.Where(x => x.Id == id)
.Select(x => new AccountDto
{
Id = x.Id,
Name = x.UserFullName,
FirstName = x.FirstName,
LastName = x.LastName,
Email = x.Email,
Mobile = x.Mobile,
UserName = x.UserName,
PhotoUrl = x.PhotoUrl,
IsActive = x.IsActive,
Roles = accounts.Where(x => x.Id == id).Select(x => new RoleDto
{
Title = x.AccountRoles
.Where(x => x.IsActive == true)
.Select(x => x.Role.Title).FirstOrDefault()
}).ToList()
}).FirstOrDefault();
Can anyone help me to write the proper query?
First, this part
Roles = accounts.Where(x => x.Id == id).Select(x => new RoleDto
{
Title = x.AccountRoles
.Where(x => x.IsActive == true)
.Select(x => x.Role.Title).FirstOrDefault()
}).ToList()
is quite strange mixture, you should simply use the navigation property (yes, it is not only for includes as some people think).
Second, don't apply FirstOrDefault() when you want to get all items rather than the first only
// here x variable type is Account (coming from the outer Select)
Roles = x.AccountRoles
.Where(ar => ar.IsActive)
.Select(ar => new RoleDto
{
Title = ar.Role.Title,
}).ToList()

Where condition in Entity Framework dose not work correctly

I have Article and ArticleTranslation tables.
When I use this query, it does not retrieve data:
model.CategoryList = await db.ArticleCategoryTranslations
.Where(x => x.LangId == lang.Id &&
x.ArticleCategory.IsActive.Value == true &&
x.ArticleCategory.IsDelete.Value == false)
.Select(x => new ddl { Id = x.RecordId.Value, Name = x.Title }).ToListAsync();
but when I use this it works, Tell me what problem in the first code
model.CategoryList = await db.ArticleCategoryTranslations
.Where(x => x.LangId == lang.Id &&
db.ArticleCategorys.Where(u => u.Id == x.RecordId).FirstOrDefault().IsActive == true &&
db.ArticleCategorys.Where(u => u.Id == x.RecordId).FirstOrDefault().IsDelete == false
)
.Select(x => new ddl { Id = x.RecordId.Value, Name = x.Title }).ToListAsync();
I don't know what the properties on your model objects look like but comparing both code snippets I see in the successful one the IsActive and IsDelete properties don't call the Value property i.e IsActive.Value and IsDelete.Value.
So your code should look like
model.CategoryList = await db.ArticleCategoryTranslations
.Where(x => x.LangId == lang.Id &&
x.ArticleCategory.IsActive == true &&
x.ArticleCategory.IsDelete == false)
.Select(x => new ddl { Id = x.RecordId.Value, Name = x.Title }).ToListAsync();
This assumes you have your navigation properties done right.

Filter null values of the entity framework query

var invoice = (from i in Catalog.Invoices
where (i.Id == invoiceId)
select i)
.Include(i => i.Appointment.Service)
.Include(i => i.Appointment.Allocations.Select(a => a.Service))
.Include(i => i.Appointment.Allocations.Select(e => e.Employee))
.FirstOrDefault();
var inv = invoice.Appointment.Allocations.Select(e => e.Employee);
My Question : How to filter the null values from above query ?
You should add a Where clause to the query to filter out the null values.
Either after the Select:
var inv = invoice.Appointment.Allocations.Select(e => e.Employee).Where(e => e != null);
or before the Select:
var inv = invoice.Appointment.Allocations.Where(e => e.Employee != null).Select(e => e.Employee);

Projection with child entities

I have the following entity framework query where I got 40 items:
context.Questions
.Where(x =>
x.Access >= 1 &&
x.Enabled == true
).ToList();
Then I tried a projection as follows:
context.Questions
.Where(x =>
x.Access >= 1 &&
x.Enabled == true
)
.Select(x => new {
Duration = x.Duration,
Text = x.Text,
Answers = x.Answers.Select(y => new {
Correct = y.Correct,
Text = y.Text
})
}).ToList();
In this case I get 150 items ... What am i doing wrong?
Basically I need the list of questions and each question to have a list of answers.
Thank You,
Miguel
Give this a try
context.Questions
.Where(x =>
x.Access >= 1 &&
x.Enabled == true
)
.Select(u => new {
Duration = u.Duration,
Text = u.Text,
Answers = u.Answers.Select(y => new {
Correct = y.Correct,
Text = y.Text
})
}).ToList();
The reason this solved your problem is because before you were using
.Select(x => ..)
where x=> references your original .Where(x =>) so it is referencing your full list of objects, not the filtered list from your where query.