I have 2 API endpoints which have similarities so I am trying to reuse some similar code. I have an EF Core method syntax to retrieve data and this query is used in both.
Rather than repeat it in both, as the Select()
s are identical, I am trying to put it into a method.
This is one of the queries
var exhibitors = await Db.CompanyDescriptions
.Join(Db.Companies, cd => cd.CompanyId, c => c.CompanyID, (cd, c) => new { cd, c })
.Where(q => uniques.Any(id => id == q.cd.CompanyId)).Where(q => q.cd.EventId == eventId)
.Select(s => new ExhibitorModel()
{
Id = s.cd.Id,
EventId = s.cd.EventId,
}).ToListAsync();
Snipped for brevity, but I have this same code in another method (mostly) and then the methods go separate ways in terms of the unit of work, so I am trying to do something like this:
private ExhibitorModel MarshallExhibitorModel(CompanyDescriptions cd, Company c)
{
return new ExhibitorModel()
{
Id = cd.Id,
EventId = cd.EventId,
};
}
And then be able to use that in both Select()
s, but I am unsure of how to form that syntax.
In this line
.Select(s => new ExhibitorModel()
How can I say call MarshallExhibitorModel and pass in s.companydescription
and s.company
?
Here you have to do expression expanding. It means that you have to preprocess Expression Tree before feeding LINQ Provider with the query. Easiest way to do that is using LINQKit
Create function which returns Lambda Expression with the same parameters types:
public static Expression<Func<CompanyDescriptions, Company, ExhibitorModel>> MarshallExhibitorModel()
{
return (cd, c) => ExhibitorModel()
{
Id = cd.Id,
EventId = cd.EventId,
};
}
And then use this function in your query. Don't forget to call AsExpandable()
at least once in the query.
var exhibitors = await Db.CompanyDescriptions
.Join(Db.Companies, cd => cd.CompanyId, c => c.CompanyID, (cd, c) => new { cd, c })
.Where(q => uniques.Any(id => id == q.cd.CompanyId)).Where(q => q.cd.EventId == eventId)
.AsExpandable() // important
.Select(s => MarshallExhibitorModel().Invoke(s.cd, s.c))
.ToListAsync();
Even better you can use such function in different situations:
...
.AsExpandable() // important
.Select(s => new SomeDTO
{
Exhibitor = MarshallExhibitorModel().Invoke(s.cd, s.c))
}
.ToListAsync();
This approach also can be used for generating complex reusable predicates which depend on parameters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With