I am loading the child entity UserStarted from my TransactionDetails
var result = (from A in context.Transactions.Include(_ => _.TransactionDetails.Select(us => us.UserStarted))
select A).SingleOrDefault();
Now I want to load another entity, but I don't know how. The entity is similar to UserStarted, it's the UserEnded also from TransactionDetails
Thank you very much
You can chain multiple include predicates together:
var result = context.Transactions
.Include(transaction => transaction.TransactionDetails.Select(us => us.UserStarted))
.Include(transaction => transaction.TransactionDetails.Select(us => us.UserEnded))
.SingleOrDefault();
You can also try
var result = (from A in context.Transactions.Include(_ => _.TransactionDetails.Select(us => new { UserStarted = us.UserStarted, UserEnded = us.UserEnded }))
select A).SingleOrDefault();
Related
I am using .NET Core 3.1. I have a parent with thousands of child elements, but I only want to retrieve the latest 10 children (and later will use pagination). When I run the following query:
context.Parent.Include(p => p.Child)
it will return all children and is incredibly slow. How can I return only 10 children and later use it for pagination? EF prevents using lambdas inside the Include, for example context.Parent.Include(p => p.Child.Take(10)) throws an exception.
Do I need multiple calls to the DB?
I hope this query helps.
var result = Parentlist
.Select(a => new { a, Childs = a.Childs.Take(10).ToList() })
.AsEnumerable()
.Select(x =>
{
x.a.Childs = x.Childs;
return x.a;
}).ToList();
var model = context.parent.Where(condition).OrderBy(x).Take(y).Skip(z)
.select(c=> new parentViewModel
{
Id = c.Id,
Name= c.Name,
children = c.children.where(condition)
.OrderByDescending(x=> x.CreateDate)
.take(pageSize)
.Select(x => new childViewModel {
Id = x.Id,
ChildName = x.Name
});
});
What if you write the query starting from the children
Context.Chidlren.Where(x => condition ( x.Parent)).Include(x => x.Parent).Take(10).Select(x=> x.Parent)
I am trying to eager load some properties using Include method as following:
var dbData = dbContext.Locators.Include(x => x.PhysicalObjects.Select(p => p.Parent)).Include(x => x.PhysicalObjects.Select(p =>p.Type.AllowedSubTypes))
.Where(x => x.id==1)).Select(x => new
{
newContainer = x.PhysicalObjects.Where(p => p.Id== newContainerId).FirstOrDefault(),
phyiscalObject = x.PhysicalObjects.Where(p => p.Id == id).FirstOrDefault()
}).FirstOrDefault();
But it returns Parent and Type properties as null(I checked database they are not null).
So how can I eager load those properties?
P.S
I am using Entity Framework V6.1.3
Depending on DevilSuichiro's comment above the query will be like this:
var dbData = dbContext.Locators.Include(x => x.PhysicalObjects.Select(p => p.Parent)).Include(x => x.PhysicalObjects.Select(p =>p.Type.AllowedSubTypes))
.Where(x => x.Id==1)).Take(2).ToList().Select(x => new
{
newContainer = x.PhysicalObjects.Where(p => p.Id== newContainerId).FirstOrDefault(),
phyiscalObject = x.PhysicalObjects.Where(p => p.Id == id).FirstOrDefault()
}).FirstOrDefault();
It worked for me, but I will still be waiting for better answer if any.
I am using entity framework and doing a group by over a table. My query is a follows:-
var brokerPaymentLists = dbContext.BrokerPayments
.Include("PaymentDetail")
.Where(bp => bp.IdPaymentStatus == (long)EntityModel.Additions.Variables.PaymentStatus.ALLOTED)
.GroupBy(bp => bp.IdBroker,
(key, g) => new
{
IdBroker = key.Value,
BrokerPayments = g.ToList()
}).ToList();
I have included PaymentDetail but after grouping by i can see that the paymentdetail for each item in the BrokerPayments i null. Any suggestion why this is the case, also how can i do the group by such that I can my my paymentDetail insisde each of the BrokerPayments;
The eagerly loading by using Include requires the shape of the data to do not be changed since the Include is applied. In your case this means the query must return IQueryable<BrokerPayments>. But the GroupBy operator changes the shape because it returns IQueryable<IGrouping<TKey, TSource>>. Same will happen with projections and custom joins.
As a workaround you can execute grouping in LINQ to Objects like:
var brokerPaymentLists = dbContext.BrokerPayments
.Include("PaymentDetail")
.Where(bp => bp.IdPaymentStatus == (long)EntityModel.Additions.Variables.PaymentStatus.ALLOTED)
.AsEnumerable()
.GroupBy(bp => bp.IdBroker,
(key, g) => new
{
IdBroker = key.Value,
BrokerPayments = g
});
NOTE: pay attention that the query exectuion will not be defferd
I need to delete items in a collection managed by Entity 6. The items that have to be deleted are in an other list
Currently I do this :
idToDelete = model.Courses.Where(x => x.Deleted).Select(x => x.Id);
entity.Courses
.Where(ent => idToDelete.Contains(ent.Id))
.ToList()
.ForEach(ent =>
_contexte.Entry(ent).State = EntityState.Deleted);
This code works fine.
How to perform the same in only one linq instruction?
entity.Courses.RemoveRange(entity.Courses.Where(e => e.Deleted));
Actually, reading your question again, it looks like the list of IDs is in a view model, and possibly your entity model doesn't have the Deleted property. So presumably you need something rather more like what you had:
_contexte.Courses.RemoveRange(
_context.Courses.Where(c => model.Courses.Where(x => x.Deleted).Select(y => y.Id).Contains(c.Id));
...or more readably:
var idsToDelete = model.Courses.Where(c => c.Deleted).Select(e => e.Id);
var entitiesToDelete = _contexte.Courses.Where(c => idsToDelete.Contains(c.Id));
_contexte.Courses.RemoveRange(entitiesToDelete);
You can use let to declare your idToDelete within the query:
(from ent in in entity.Courses
let idsToDelete = model.Courses.Where(x => x.Deleted).Select(x => x.Id)
where idsToDelete.Contains(ent.Id)
select ent).ToList()
.ForEach(ent => _contexte.Entry(ent).State = EntityState.Deleted);
I have a query (including LinqKit) of the form:
Expression<Func<Country, DateTime, bool>> countryIndepBeforeExpr =
(ct, dt) => ct.IndependenceDate <= dt;
DateTime someDate = GetSomeDate();
var q = db.Continent.AsExpandable().Select(c =>
new
{
c.ID,
c.Name,
c.Area,
Countries = c.Countries.AsQueryable()
.Where(ct => countryIndepBeforeExpr.Invoke(ct, someDate))
.Select(ct => new {ct.ID, ct.Name, ct.IndependenceDate})
});
Now I want to iterate through q... but since the Countries property of each element is of type IQueryable, it will be lazy loaded, causing n+1 queries to be executed, which isn't very nice.
What is the correct way to write this query so that all necessary data will be fetched in a single query to the db?
EDIT
Hm, well it might have helped if I had actually run a Sql trace before asking this question. I assumed that because the inner property was of type IQueryable that it would be lazy-loaded... but after doing some actual testing, it turns out that Linq to Entities is smart enough to run the whole query at once.
Sorry to waste all your time. I would delete the question, but since it already has answers, I can't. Maybe it can serve as some kind of warning to others to test your hypothesis before assuming it to be true!
Include countries to your model when you call for continents. With something like this:
var continents = db.Continent.Include(c => c.Countries).ToArray();
Then you can make your linq operations without iQueryable object.
I think this should work (moving AsExpandable() to root of IQueryable):
var q = db.Continent
.AsExpandable()
.Select(c => new
{
c.ID,
c.Name,
c.Area,
Countries = c.Countries
.Where(ct => countryIndepBeforeExpr.Invoke(ct, someDate))
.Select(ct => new {ct.ID, ct.Name, ct.IndependenceDate})
});
If not, create two IQueryable and join them together:
var continents = db.Continents;
var countries = db.Countries
.AsExpandable()
.Where(c => countryIndepBeforeExpr.Invoke(c, someDate))
.Select(c => new { c.ID, c.Name, c.IndependenceDate });
var q = continents.GroupJoin(countries,
continent => continent.ID,
country => country.ContinentId,
(continent, countries) => new
{
continent.ID,
continent.Name,
continent.Area,
Countries = countries.Select(c => new
{
c.ID,
c.Name,
c.IndependenceDate
})
});