I have my object-to-object mapping code (using automapper) in service layer with lazy-loading enabled:
public IEnumerable<TaskViewModel> MapToView(IEnumerable<IRAS_PM_TaskAssignment> models)
{
Mapper.CreateMap<IRAS_PM_TaskAssignment, TaskViewModel>()
.ForMember(t => t.AssetOrShotName, map => map.MapFrom(t => t.IRAS_PM_Asset_Sequence.AssetShotName))
.ForMember(t => t.Days, map => map.MapFrom(t => (t.StartDate.HasValue && t.DeadLine.HasValue)
? t.DeadLine.Value.Subtract(t.StartDate.Value).TotalDays
: 0.0))
.ForMember(t => t.DepartmentName, map => map.MapFrom(t => t.IRAS_PM_DepartmentName.DeptName));
return models.Select(x => Mapper.Map<IRAS_PM_TaskAssignment, TaskViewModel>(x));
}
And my controller call is:
public ActionResult TaskRead([DataSourceRequest] DataSourceRequest request, int? projectId)
{
var tasks = projectId.HasValue
? _taskRepository.MapToView(_taskRepository.FindBy(x => x.ProjectId == projectId).ToList())
: _taskRepository.MapToView(_taskRepository.All.ToList());
return Json(tasks.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
When inspecting EF-queries, miniprofiler warns me for duplicate reader queries:
What am i doing wrong? please help me to remove redundant readers.
The issue is on this line:
.ForMember(t => t.DepartmentName, map => map.MapFrom(t => t.IRAS_PM_DepartmentName.DeptName));
For every IRAS_PM_TaskAssignment entity here, you are loading looking up the IRAS_PM_DepartmentName that is related to that entity, and getting its department name.
Because of Lazy Loading, these are called one at a time, for every row you are loading.
The solution is to perform eager loading on the IRAS_PM_DepartmentName entity relates to your base IRAS_PM_TaskAssignment. The code to do this remove this:
_taskRepository.FindBy(x => x.ProjectId == projectId).ToList();
And instead use something like this:
_taskRepository.FindBy(x => x.ProjectId == projectId)
.Include(x => x.IRAS_PM_TaskAssignment)
.ToList();
You can make a similar change to the unfiltered retrieval.
The Include statement should pull down each of those related items in the initial query, eliminating the need to look each one up subsequently, one at a time.
Related
I'm trying to filter on the initial query. I have nested include leafs off a model. I'm trying to filter based on a property on one of the includes. For example:
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList();
}
How can I also say .Where(w => w.post.Author == "me")?
Entity Framework core 5 is the first EF version to support filtered Include.
How it works
Supported operations:
Where
OrderBy(Descending)/ThenBy(Descending)
Skip
Take
Some usage examples (from the original feature request and the github commmit)
:
Only one filter allowed per navigation, so for cases where the same navigation needs to be included multiple times (e.g. multiple ThenInclude on the same navigation) apply the filter only once, or apply exactly the same filter for that navigation.
context.Customers
.Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.OrderDetails)
.Include(c => c.Orders).ThenInclude(o => o.Customer)
or
context.Customers
.Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.OrderDetails)
.Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.Customer)
Another important note:
Collections included using new filter operations are considered to be loaded.
That means that if lazy loading is enabled, addressing one customer's Orders collection from the last example won't trigger a reload of the entire Orders collection.
Also, two subsequent filtered Includes in the same context will accumulate the results. For example...
context.Customers.Include(c => c.Orders.Where(o => !o.IsDeleted))
...followed by...
context.Customers.Include(c => c.Orders.Where(o => o.IsDeleted))
...will result in customers with Orders collections containing all orders.
Filtered Include and relationship fixup
If other Orders are loaded into the same context, more of them may get added to a customers.Orders collection because of relationship fixup. This is inevitable because of how EF's change tracker works.
context.Customers.Include(c => c.Orders.Where(o => !o.IsDeleted))
...followed by...
context.Orders.Where(o => o.IsDeleted).Load();
...will again result in customers with Orders collections containing all orders.
The filter expression
The filter expression should contain predicates that can be used as a stand-alone predicate for the collection. An example will make this clear. Suppose we want to include orders filtered by some property of Customer:
context.Customers.Include(c => c.Orders.Where(o => o.Classification == c.Classification))
It compiles, but it'll throw a very technical runtime exception, basically telling that o.Classification == c.Classification can't be translated because c.Classification can't be found. The query has to be rewritten using a back-reference from Order to Customer:
context.Customers.Include(c => c.Orders.Where(o => o.Classification == o.Customer.Classification))
The predicate o => o.Classification == o.Customer.Classification) is "stand alone" in the sense that it can be used to filter Orders independently:
context.Orders.Where(o => o.Classification == o.Customer.Classification) // No one would try 'c.Classification' here
This restriction may change in later EF versions than the current stable version (EF core 5.0.7).
What can (not) be filtered
Since Where is an extension method on IEnumerable it's clear that only collections can be filtered. It's not possible to filter reference navigation properties. If we want to get orders and only populate their Customer property when the customer is active, we can't use Include:
context.Orders.Include(o => o.Customer.Where( ... // obviously doesn't compile
Filtered Include vs filtering the query
Filtered Include has given rise to some confusion on how it affects filtering a query as a whole. The rule of the thumb is: it doesn't.
The statement...
context.Customers.Include(c => c.Orders.Where(o => !o.IsDeleted))
...returns all customers from the context, not only the ones with undeleted orders. The filter in the Include doesn't affect the number of items returned by the main query.
On the other hand, the statement...
context.Customers
.Where(c => c.Orders.Any(o => !o.IsDeleted))
.Include(c => c.Orders)
...only returns customers having at least one undeleted order, but having all of their orders in the Orders collections. The filter on the main query doesn't affect the orders per customer returned by Include.
To get customers with undeleted orders and only loading their undeleted orders, both filters are required:
context.Customers
.Where(c => c.Orders.Any(o => !o.IsDeleted))
.Include(c => c.Orders.Where(o => !o.IsDeleted))
Filtered Include and projections
Another area of confusion is how filtered Include and projections (select new { ... }) are related. The simple rule is: projections ignore Includes, filtered or not. A query like...
context.Customers
.Include(c => c.Orders)
.Select(c => new { c.Name, c.RegistrationDate })
...will generate SQL without a join to Orders. As for EF, it's the same as...
context.Customers
.Select(c => new { c.Name, c.RegistrationDate })
It gets confusing when the Include is filtered, but Orders are also used in the projection:
context.Customers
.Include(c => c.Orders.Where(o => !o.IsDeleted))
.Select(c => new
{
c.Name,
c.RegistrationDate,
OrderDates = c.Orders.Select(o => o.DateSent)
})
One might expect that OrderDates only contains dates from undeleted orders, but they contain the dates from all Orders. Again, the projection completely ignores the Include. Projection and Include are separate worlds.
How strictly they lead their own lives is amusingly demonstrated by this query:
context.Customers
.Include(c => c.Orders.Where(o => !o.IsDeleted))
.Select(c => new
{
Customer = c,
OrderDates = c.Orders.Select(o => o.DateSent)
})
Now pause for a moment and predict the outcome...
The not so simple rule is: projections don't always ignore Include. When there is an entity in the projection to which the Include can be applied, it is applied. That means that Customer in the projection contains its undeleted Orders, whereas OrderDates still contains all dates. Did you get it right?
Not doable.
There is an on-going discussion about this topic:
https://github.com/aspnet/EntityFramework/issues/1833
I'd suggest to look around for any of the 3rd party libraries listed there, ex.: https://github.com/jbogard/EntityFramework.Filters
You can also reverse the search.
{
var blogs = context.Author
.Include(author => author.posts)
.ThenInclude(posts => posts.blogs)
.Where(author => author == "me")
.Select(author => author.posts.blogs)
.ToList();
}
Not sure about Include() AND ThenInclude(), but it's simple to do that with a single include:
var filteredArticles =
context.NewsArticles.Include(x => x.NewsArticleRevisions)
.Where(article => article.NewsArticleRevisions
.Any(revision => revision.Title.Contains(filter)));
Hope this helps!
Although it's (still in discussion) not doable with EF Core, I've managed to do it using Linq to Entities over EF Core DbSet. In your case instead of:
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList()
.. you'll have:
await (from blog in this.DbContext.Blogs
from bPost in blog.Posts
from bpAuthor in bPost.Author
where bpAuthor = "me"
select blog)
.ToListAsync();
I used below package
Use Z.EntityFramework.Plus
IncludeFilter and IncludeFilterByPath two methods are which you can use.
var list = context.Blogs.IncludeFilter(x => x.Posts.Where(y => !y.IsSoftDeleted))
.IncludeFilter(x => x.Posts.Where(y => !y.IsSoftDeleted)
.SelectMany(y => y.Comments.Where(z => !z.IsSoftDeleted)))
.ToList();
Here is the example https://dotnetfiddle.net/SK934m
Or you can do like this
GetContext(session).entity
.Include(c => c.innerEntity)
.Select(c => new Entity()
{
Name = c.Name,
Logo = c.Logo,
InnerEntity= c.InnerEntity.Where(s => condition).ToList()
})
Interesting case and it worked!!
If you have table/model user(int id, int? passwordId, ICollection<PwdHist> passwordHistoryCollection) where collection is history of passwords. Could be many or none.
And PwdHistory(int id, int UserId, user User). This has a quasi relationship via attributes.
Needed to get user, with related current password record, while leaving historical records behind.
User user = _userTable
.Include(u => u.Tenant)
.Include(u => u.PwdHistory.Where(p => p.Id == p.PwdUser.PasswordId))
.Where(u => u.UserName == userName)
.FirstOrDefault();
Most interesting part is .Include(u => u.PwdHistory.Where(p => p.Id == p.PwdUser.PasswordId))
works with user and many passwords
works with user and no passwords
works with no user
We can use by extension
public static IQueryable<TEntity> IncludeCondition<TEntity, TProperty>(this IQueryable<TEntity> query, Expression<Func<TEntity, TProperty>> predicate, bool? condition) where TEntity : class where TProperty : class
{
return condition == true ? query.Include(predicate) : query;
}
Usage;
_context.Tables.IncludeCondition(x => x.InnerTable, true)
This task can be accomplished with two queries. For example:
var query = _context.Employees
.Where(x =>
x.Schedules.All(s =>
s.ScheduleDate.Month != DateTime.UtcNow.AddMonths(1).Month &&
s.ScheduleDate.Year != DateTime.UtcNow.AddMonths(1).Year) ||
(x.Schedules.Any(s =>
s.ScheduleDate.Month == DateTime.UtcNow.AddMonths(1).Month &&
s.ScheduleDate.Year == DateTime.UtcNow.AddMonths(1).Year) &&
x.Schedules.Any(i => !i.ScheduleDates.Any())));
var employees = await query.ToListAsync();
await query.Include(x => x.Schedules)
.ThenInclude(x => x.ScheduleDates)
.SelectMany(x => x.Schedules)
.Where(s => s.ScheduleDate.Month == DateTime.UtcNow.AddMonths(1).Month &&
s.ScheduleDate.Year == DateTime.UtcNow.AddMonths(1).Year).LoadAsync();
I have a method that retrieves an Entity from a database using nHibernate. It's quite a complex Entity:
Level4 has many Level3s which have many Level2s which have many Level1s which has a Level1Ref
So I use a few futures like this:
var future = this.Session.QueryOver<Level4>()
.Where(x => x.Id == level4Id)
.Fetch(x => x.Level3List).Eager
.Fetch(x => x.Level3List.First().Level2List).Eager
.Left.JoinAlias(x => x.Level3List, () => level3Alias, x => x.AnotherThing.Id == anotherThingId)
.FutureValue();
And some queries like this:
this.Session.QueryOver<Level1>()
.Fetch(x => x).Eager
.Fetch(x => x.Level1Ref).Eager
.Fetch(x => x.Level2).Eager
.Inner.JoinAlias(x => x.Level2, () => level2Alias)
.Inner.JoinAlias(() => level2Alias.Level3, () => level3Alias, x => x.AnotherThing.Id == anotherThingId && level3Alias.Level4.Id == level4Id)
.Future();
And then:
var record = future.Value;
This all generates the SQL that I would expect but when I try to iterate over the Level2.Level1List it lazy loads the records in that list.
The Question:
This is the problem. What have I? done wrong in my query that nHibernate thinks it needs to go to the database for information that it has already got? (I've got a hunch that I need to swap some of my JoinQueryOver bits for eager fetches?
(Questions edited to simplify examples)
After lots of investigation the only way I could get this working was change all of my queries so they have the same TRoot. Ie. Change them so they all start like this:
this.Session.QueryOver<Level4>()
This obviously isn't ideal in situations like this:
FishMonger
Collection of Fish
Collection of Eye
Collection of Bone
It means I have to write two queries and join in Fish twice...
The alternative is to lazy load and batch the queries but the requirement is to make only one round trip to the database.
I am using NHibernate with mapping by code.
I have three models: Solution, Installation and System. There are one-to-many relations between them. So that each Solution has a list of Installations, and each Installation has a list of Systems.
Each system has a property "Type", which can be "1" or "0".
I am trying to write a method in the Solution repository that will return all the Solutions, with their Installations with only the Systems of type "1".
I have tried the Where-keyword in the SystemMap but i get the same result with and without it. Then i tried a few different experiments with QueryOver(???) without success.
How do i go about to filter on information in the last node?
Thank to your answer, i have done the following implementation, but it results in a huge amount of Systems and Solutions. Maybe i have done something wrong?
The Maps are as follows:
public SAPSolutionMap()
{
Id(t => t.YPID);
Property(e => e.ShortName);
Property(e => e.FullName);
Bag(x => x.SapInstallations, colmap =>
{
colmap.Table("SAPInstallation");
colmap.Key(x => x.Column("Solution"));
colmap.Inverse(true);
colmap.Lazy(CollectionLazy.NoLazy);
colmap.Fetch(CollectionFetchMode.Join);
colmap.Cascade(Cascade.None);
}, map => map.OneToMany(m => m.Class(typeof(SAPInstallation))));
}
public SAPInstallationMap()
{
Id(t => t.InstallationNumber);
Bag(x => x.SapSystems, colmap =>
{
colmap.Table("sapgui");
colmap.Key(x => x.Column("Installation"));
colmap.Inverse(true);
colmap.Lazy(CollectionLazy.NoLazy);
colmap.Cascade(Cascade.None);
colmap.Fetch(CollectionFetchMode.Join);
//colmap.Where("Type = 1");
}, map => map.OneToMany(m => m.Class(typeof(SAPSystem))));
ManyToOne(x => x.SapSolution, map =>
{
map.Column("Solution");
map.NotNullable(true);
map.Cascade(Cascade.None);
map.Class(typeof(SAPSolution));
});
}
public SAPSystemMap()
{
Id(t => t.ID, t => t.Generator(Generators.Identity));
Property(e => e.Type);
Property(e => e.ExplanationText);
ManyToOne(x => x.SapInstallation, map =>
{
map.Column("Installation");
map.NotNullable(true);
map.Cascade(Cascade.None);
map.Class(typeof(SAPInstallation));
});
}
And the Query:
public IList<SAPSolution> GetProductionSystems()
{
SAPSystem syst = null;
SAPInstallation installation = null;
var subquery = QueryOver.Of(() => syst)
.JoinQueryOver(x => x.SapInstallation, () => installation)
.Where(() => syst.Type == 1)
.Select(x => installation.SapSolution.YPID);
// main Query
var query = Session.QueryOver<SAPSolution>()
.WithSubquery
.WhereProperty(root => root.YPID)
.In(subquery);
return query.List<SAPSolution>();
}
Thank you!
General solution should be:
// this is a subquery (SELECT ....
System syst = null;
Installation installation = null;
var subquery = QueryOver.Of(() => syst)
.JoinQueryOver(x => x.Installation, () => installation)
.Where(() => syst.Type == 1)
.Select(x => installation.Solution.ID)
;
// main Query
var query = session.QueryOver<Solution>()
.WithSubquery
.WhereProperty(root => root.ID)
.In(subquery)
;
var list = query
.Take(10)
.Skip(10)
.List<Solution>();
What we can see, that Solution, Installation and System
System has property Installation (many-to-one)
Installation has property Solution (many-to-one)
This is expect-able, because it goes side by side with one-to-many (it is the reverse mapping)
So, then we create subquery, which returns just solution ID's which belong to system with searched Type.
Main query is flat (the great benefit) and we can use paging on top of it.
We would be able to do that even if there is only one way (one-to-many). But that will generate more complicated SQL query ... and does not make sense. In C# we can have both relations...
EXTEND:
You did a great job. Your mapping and query is really cool. But there is one big but: LAZY is what we should/MUST use. Check this:
NHibernate is lazy, just live with it, by Ayende
So, our, collections cannot be FETCHING with a JOIN, because that will multiply the result (10 solutions * 100 installation * 10 systems == 10000 results)
Bag(x => x.SapSystems, colmap =>
{
...
// THIS IS not good way
colmap.Lazy(CollectionLazy.NoLazy);
colmap.Fetch(CollectionFetchMode.Join);
We should use LAZY as possible. To avoid later 1 + N issue, we can use batch-fetching (for example check this)
How to Eager Load Associations without duplication in NHibernate?
So, our collections should be mapped like this:
Bag(x => x.SapSystems, colmap =>
{
...
// THIS IS not good way
colmap.Lazy(CollectionLazy.Lazy);
colmap.BatchSize(100);
With this setting, the query will really use only the root object and related collections will be loaded very effectively
I have a data model like this
I would like to load all the related entities from a Reconciliation into a Reconciliation object.
For now the only way I could find to load all the related entites to a single Recon is in multiple Lists. But I want to load every related entities in a Reconciliation object. If possible in an elegant way.
Reconciliation recon = db.Reconciliations
.Where(r => r.ReconNum == 382485).First();
List<ReconciliationDetail> reconDetails = recon.ReconciliationDetails.ToList();
List<JrnlEntryDetail> jrnlDetails = reconDetails.Select(r => r.JrnlEntryDetail).ToList();
List<JrnlEntry> jrnl = jrnlDetails.Select(j => j.JrnlEntry).ToList();
List<ARInvoice> invoices = jrnl.SelectMany(j => j.ARInvoices).ToList();
List<ARInvoiceDetail> invoicesDetail = invoices
.SelectMany(i => i.ARInvoiceDetails).ToList();
List<ARCredMemo> credmemos = jrnl.SelectMany(j => j.ARCredMemoes).ToList();
List<ARCredMemoDetail> credmemosDetail = credmemos
.SelectMany(c => c.ARCredMemoDetails).ToList();
List<IncomingPay> incomingPays = jrnl.SelectMany(j => j.IncomingPays).ToList();
List<IncomingPayDetail> incomingPaysDetail = incomingPays
.SelectMany(i => i.IncomingPayDetails).ToList();
// ... and so on for outgoing pays, AP Invoices AP Cred Memo ...etc
I have also tried to load it with Include and Select but I get this exception :
The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
And I don't get how I could load every childs of JrnlEntry using Include and Select
Reconciliation recon = db.Reconciliations
.Where(r => r.ReconNum == 382485)
.Include(r => r.ReconciliationDetails
.Select(d => d.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry)
.SelectMany(j => j.ARInvoices).SelectMany(i => i.ARInvoiceDetails))
Edit
Managed to do it this way too but it's not very beautiful :
Reconciliation recon = db.Reconciliations
.Where(r => r.ReconNum == 382485)
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.ARInvoices.Select(i => i.ARInvoiceDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.ARCredMemoes.Select(c => c.ARCredMemoDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.IncomingPays.Select(i => i.IncomingPayDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.OutgoingPays.Select(o => o.OutgoingPayDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.APInvoices.Select(o => o.APInvoiceDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.APCredMemoes.Select(o => o.APCredMemoDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.JrnlEntryDetails))
There are two ways to perform Eager Loading in Entity Framework:
ObjectQuery.Include Method
Explicit loading using either DbEntityEntry.Collection Method or DbEntityEntry.Reference Method along with their respective Load methods
There are also manners to write Raw SQL Queries against database:
DbSet.SqlQuery Method deals with entities
Database.SqlQuery Method deals with arbitrary types
Database.ExecuteSqlCommand Method for arbitrary DDL/DML
For the case, when you're attempting to load nearly entire database, it would be good idea to execute dedicated store procedure against it.
Try with just .Include(r => r.ReconciliationDetails) initially. Then add the .Select() statements one-by-one. At what point does the exception reappear? The .SelectMany() call looks a bit suspicious to me!
A second question that might help identify the problem... After you run the code that contains all the ToList() calls, is your recon entity complete? i.e. are all its navigation properties populated? This should be the case because of the automatic 'fixup' behavior of Entity Framework.
With EF, sometimes it is more efficient to load a complex object graph with several calls rather than chained Include() calls. Check the generated SQL and see what is most efficient in your case.
Not sure if it's to late but could you benefit from structuring your code such as
var acctName = "someName";
var detailList = _repository.Include(e => e.JrnlEntryDetail).Filter(c => c.JrnlEntryDetail.Any(e => e.AcctName == acctName)).Get().ToList();
I a portion of my EF model that looks like this:
Summary:
Location has many Posts
Post is an abstract class
Discussion derives from Post
Discussions have many Comments
Now, the query i'm trying to achieve:
Get information about Location Id 1234, including any Discussions and Comments associated with those Discussions.
I can get discussions and the comments like this:
var discussions = ctx.Posts
.OfType<Discussion>()
.Include(x => x.Comments)
.ToList();
But i can't seem to get it based on the Posts navigation on the Location entity.
I've tried this:
var locationWithDiscussionsAndComments = ctx
.Locations
.Include(x => x.Posts
.OfType<Discussion>()
.Select(y => y.Comments))
.SingleOrDefault();
Which compiles, but i get the error:
System.ArgumentException: The include path expression must refer to a property defined by the entity, optionally also with nested properties or calls to Select.
Parameter name: path
Any ideas? I could probably go "backwards" from the Posts:
var locationWithDiscussionsAndComments = ctx
.Posts
.Include(x => x.Location)
.OfType<Discussion>()
.Include(x => x.Comments)
.Where(x => x.LocationId == 1234)
.Select(x => x.Location)
.ToList();
But that is both hairy and semantically wrong in terms of my repositories (i shouldn't have to go through a post repository to get information about a location).
Any ideas?
EDIT
So after having a bigger think about it, i realized that OfType<T> is a filter operation. As as we know, EF does not support filtering with eager loading. The only options are retrieving everything, or using anonymous type projection.
No way i can retrieve everything, as there is far too much meta data involved. So i'm attempting the anonymous type projection.
The new Query method might help you:
var location = context.Locations.SingleOrDefault();
context.Entry(location)
.Collection(l => l.Posts)
.Query()
.OfType<Discussion>()
.Load();
Repository Implementation:
We can add a new LoadProperty generic method to the Repository<T> class that leverages this new QUery method:
public void LoadProperty<TElement>(T entity,
Expression<Func<T, ICollection<TElement>>> navigationProperty,
Expression<Func<TElement, bool>> predicate) where TElement : class
{
_context.Set<T>().Attach(entity);
_context.Entry(entity)
.Collection(navigationProperty)
.Query()
.Where(predicate)
.Load();
}
Using the LoadProperty method:
Location location = _locationRepository.Find(1);
_locationRepository.LoadProperty(location, l => l.Posts, p => p is Discussion);