Change query value based on parameter [duplicate] - c#

This question already has answers here:
Creating reusable Linq queries
(6 answers)
Closed 8 years ago.
I have a query:
doc.NonFinancialAssetSection.NonFinancialAssets
.Where(m => m.Owner.Id == ownerId && m.InvestableAsset == true)
.Sum(s => s.CurrentValue);
I need to change the value of s.CurrentValue to s.ProposedValue, however rather than copying and pasting the query again, is there any way i can have this value dependant on a parameter passed into the controller?

Yes, you can do this:
var query = doc.NonFinancialAssetSection.NonFinancialAssets
.Where(m => m.Owner.Id == ownerId && m.InvestableAsset == true);
var sum = (condition)
? query.Sum(s => s.CurrentValue)
: query.Sum(s => s.ProposedValue);
You could also do this:
var sum = doc.NonFinancialAssetSection.NonFinancialAssets
.Where(m => m.Owner.Id == ownerId && m.InvestableAsset == true)
.Sum(s => (condition) ? s.CurrentValue : s.ProposedValue);
Or this:
Func<NonFinancialAsset, double> sumProperty = (condition)
? s => s.CurrentValue
: s => s.ProposedValue;
var sum = doc.NonFinancialAssetSection.NonFinancialAssets
.Where(m => m.Owner.Id == ownerId && m.InvestableAsset == true)
.Sum(sumProperty);

Related

how to conditionally add where condition in linq [duplicate]

This question already has answers here:
Linq dynamically adding where conditions
(3 answers)
Closed 2 years ago.
I am using entity framework and i want to add a where condition only if the condition is met else i dont want that where to be executed which i want to do it in 1 query
Context.Test
.Where(v => v.Valuation.ValuationPeriod.PeriodName == periodName && parameters.SelectedTemplateIds.Contains(v.TemplateTypeId) && fundBusinessIds.Contains(v.Fund.BusinessId))
.Where(v => parameters.sortedList.Contains(v.Valuation.PortfolioCompany.DealCode))
.Where(v => wpGroup == null || v.Valuation.PortfolioCompany.WPGroup == wpGroup)
.Where(v => !myDeals || v.Valuation.PortfolioCompany.UserPermission.Any(up => up.UserId == userId))
so in the above query
Where(v => parameters.sortedList.Contains(v.Valuation.PortfolioCompany.DealCode))
I want to execute only if
parameters.sortedList.Count() > 0
else i dont want to include that where condition in the above query. So basically here i know we can do by seperating the query that is first get a list of values and then check this condition and if it matches then add a where on that list. But is it possible without doing that?
The filter could be added contitionally as follows by using an intermediate assignment.
var result = Context.Test.Where(v => v.Valuation.ValuationPeriod.PeriodName == periodName && parameters.SelectedTemplateIds.Contains(v.TemplateTypeId) && fundBusinessIds.Contains(v.Fund.BusinessId));
if (parameters.sortedList.Count() > 0)
{
result = result.Where(v => parameters.sortedList.Contains(v.Valuation.PortfolioCompany.DealCode));
}
result = result.Where(v => wpGroup == null || v.Valuation.PortfolioCompany.WPGroup == wpGroup)
.Where(v => !myDeals || v.Valuation.PortfolioCompany.UserPermission.Any(up => up.UserId == userId));
You can use this
.Where(v => parameters.sortedList.Count() > 0 ?
parameters.sortedList.Contains(v.Valuation.PortfolioCompany.DealCode) : true)
LINQ queries don't execute unless you do something that causes enumeration of the resulting IEnumerable, which means you can have a pattern of:
var x = collection.Where(...);
if(sometest)
x = x.Where(..);
var result = x.ToList(); //enumerate, causing evaluation
If sometest is true then both the Where will apply (AND style; both where predicates would have to result in a true for a collection entity to appear in the result), if sometest is false, then only the first Where applies
You can add an extension
public static class WhereIfExtension
{
public static IEnumerable<TCollection> WhereIf<TCollection>(this IEnumerable<TCollection> source,
bool condition, Func<TCollection, bool> predicate)
{
return condition ? source.Where(predicate) : source;
}
public static IQueryable<TCollection> WhereIf<TCollection>(this IQueryable<TCollection> source, bool condition,
Expression<Func<TCollection, bool>> predicate)
{
return condition ? source.Where(predicate) : source;
}
}
then
Context.Test
.Where(v => v.Valuation.ValuationPeriod.PeriodName == periodName && parameters.SelectedTemplateIds.Contains(v.TemplateTypeId) && fundBusinessIds.Contains(v.Fund.BusinessId))
.WhereIf(parameters => parameters.sortedList.Count() > 0, parameters.sortedList.Contains(v.Valuation.PortfolioCompany.DealCode))
.Where(v => wpGroup == null || v.Valuation.PortfolioCompany.WPGroup == wpGroup)
.Where(v => !myDeals || v.Valuation.PortfolioCompany.UserPermission.Any(up => up.UserId == userId))

Compare 2 List - LINQ [duplicate]

This question already has answers here:
C# Linq intersect/except with one part of object
(7 answers)
Closed 3 years ago.
There are 2 large list of objects, where I need to do a where clause and find the matching records.
List<A> a= ...;
List<A> b = ...;
A model
Id
Name
Age
Address
I need to return a list that contains all the object of List after comparing with List.
The properties I should check is : If the Ids are equal, if the Names are equal and if the ages are equal.
List<A> common = a.Where(n => b.Select(o => o.Id).Contains(n.Id))
.Where(n => b.Select(o => o.Name).Contains(n.Name))
.Where(n => b.Select(o => o.Age).Contains(n.Age))
There should be something wrong with this, as it returns a Null.
You can create custom EqualityComparer:
public class ModelEqualityComparer : IEqualityComparer<Model>
{
public bool Equals(Model x, Model y)
{
return x.Id == y.Id && x.Name == y.Name && x.Age == y.Age;
}
...
}
And use it like this:
var intersect = a.Intersect(b, new ModelEqualityComparer());
If you want just LINQ solution:
List<Model> common = a
.Where(q => b.Any(w => w.Id == q.Id && w.Name == q.Name && q.Age == w.Age))

LINQ to Entities does not recognize the method - subquery count

Hi this question has been asked before but I'm struggling to find an answer that matches my question (the error comes up a lot).
This looks to be similar but with 4 years ago has there been any progress.
LINQ to Entities does not recognize the method 'Int32
Basically I want to move a subquery that returns a count into a function anyway here's the code.
vm.SicknessEpisodes = _db.SicknessEpisodes.Where(x => x.Status == true && x.LastDay == null).OrderByDescending(x => x.FirstDay).
Select(x => new HomeSicknessEpisode
{
SicknessEpisode = x,
EpisodesIn12Months = _db.SicknessEpisodes.Where(y => y.StaffID == x.StaffID && y.Status == true &&
(y.LastDay == null || (y.LastDay.HasValue && y.LastDay >= prevDate))).Count()
}).
ToPagedList(p, 100);
This works
This
vm.SicknessEpisodes = _db.SicknessEpisodes.Where(x => x.Status == true && x.LastDay == null).OrderByDescending(x => x.FirstDay).
Select(x => new HomeSicknessEpisode
{
SicknessEpisode = x,
EpisodesIn12Months = _db.episodes12Months(x,prevDate).Count()
}).
ToPagedList(p, 100);
public IQueryable<SicknessEpisode> episodes12Months(SicknessEpisode x, DateTime prevDate)
{
return this.SicknessEpisodes.Where(y => y.StaffID == x.StaffID && y.Status == true &&
(y.LastDay == null || (y.LastDay.HasValue && y.LastDay >= prevDate)));
}
Does not.
Can anyone tell me how I can make it work - ideally without going into a List and then foreach each episode to run the count.
I'm just trying to make it as efficient as possible for Entity Framework.
If it's not possible - then that's fine - one of those things.

multiple where in linq based on parameters value [duplicate]

This question already has answers here:
Linq to SQL multiple conditional where clauses
(3 answers)
Closed 7 years ago.
I want to have multiple where clauses in linq but out of them only one should execute, i was trying something like this:
public JsonResult GetPost(int? id, int? tagid, DateTime? date)
{
var ret = from data in db.Posts.Include(x => x.Tags)
.Include(x => x.Neighbourhood)
.Where((x => x.NeighbourhoodId == id) || (y => y.PostedDate == date) || third condition).ToList()
but i was unable to put second and third condition there becoz after putting dot after y, i cant see any options.
Now, out of these three, only one parameter would have value and other two would have null so, it should checks for parameter only with value.
should i write query like this, is it correct way:
if (id != null)
{
//whole query here
}
else if (tagid != null)
{
//whole query here
}
else (date != null)
{
//whole query here
}
Is it the best way to do this or something else is possible. many many thnks in advance for any suggestion.
Something like this?
var ret = from data in db.Posts.Include(x => x.Tags)
.Include(x => x.Neighbourhood)
.Where(x => x.NeighbourhoodId == (id ?? x.NeighbourhoodId) &&
x.<condition> == (tagid ?? x.<condition>) &&
x.PostedDate == (date ?? x.PostedDate).ToList();
Or like this:
var ret = from data in db.Posts.Include(x => x.Tags)
.Include(x => x.Neighbourhood)
.Where(x => id.HasValue ? x.NeighbourhoodId == id :
tagid.HasValue ? x.<condition> == tagid :
x.PostedDate == date).ToList();
Another option is to build your query more dynamically. I think this also makes your code more human readable, and your conditions can be more complex if needed (for example, build your query inside a loop or something). And you can use this with any other operator, like Include etc. Once your query is built, you can call ToList().
var ret = db.Posts.Include(x => x.Tags).Include(x => x.Neighbourhood);
if (id != null)
{
ret = ret.Where((x => x.NeighbourhoodId == id);
}
else
{
...
}
var result = ret.ToList();
You could use the following:
var ret = from data in db.Posts.Include(x => x.Tags)
.Include(x => x.Neighbourhood)
.Where(x => id == null || x.NeighbourhoodId == id)
.Where(x => date == null || y.PostedDate == date)
.ToList();
If the paramter is null, the where-clauses returns every element of the sequence. If its not null it only returns the elements which matches.

filtering results with Entity Framework

another kinda newbie question I guess. I have EF setup and now I want to select some records based on a filter. I have SomeClass with 4 items (all strings to keep things simple, lets call them string1, string2, and so on). Now, in a post I send the filter in an instance of SomeClass, but maybe not all properties are filled in.
So you might end up with string1="something", string2="bla" and string4="bla2". So string 3 = null. Now, how do I setup the query? If i try something like:
var dataset = entities.mydatabase
.Where(x => x.string1 == someclass.string1 && x.string2 == someclass.string2 && x.string3 == someclass.string3 && x.string4 == someclass.string4)
.Select(x => new { x.string1, x.string2, x.string3, x.string4}).ToList();
... I get no results, because string3=null. I could do something with checking all parameters and see if they're set and create the query based on that, but there must be something more elegant than that.
Anyone?
Thanks!
Ronald
The following will return all rows where the someclass.string is null OR equals to x.string.
var dataset = entities.mydatabase
.Where(x => someclass.string1 == null || x.string1 == someclass.string1)
.Where(x => someclass.string2 == null || x.string2 == someclass.string2)
.Where(x => someclass.string3 == null || x.string3 == someclass.string3)
.Where(x => someclass.string4 == null || x.string4 == someclass.string4)
.Select(x => new { x.string1, x.string2, x.string3, x.string4}).ToList();

Categories

Resources