Build predicate with lis in parameter - c#

I need to filter a list on multiple value.
It works well with basic type like string but I need to filter on 2 others filters build on list like that :
predicate.And(i => i.countries.Find(c => c.Code == country).Code == country)
First of all I'm not sure it is the good way to build this sort of predicate.
Second when predicate is built it looks like that :
{i => (i.countries.Find(c => (c.Code == value(Portail.Controllers.ProfilsController+<>c__DisplayClass21_0).country)).Code == value(Portail.Controllers.ProfilsController+<>c__DisplayClass21_0).country)}
And of course it doesnt work.
Is it possible to do such a thing and if yes, how?

Related

LinqToDB.LinqToDBException Expressionis not an association

Hi All I am trying to do below ,I want to load an attribute value like this .
var date = db.GetTable<bbb>().Where(x => idList.Contains(x.MID))
.Select(x => x.ModifiedDate).FirstOrDefault;
var test = db.GetTable<nnn>().Where(x => xguy.Distinct().Contains(x.SID))
.LoadWith(x => x.Modified == lastPostDate);
exception:-
LinqToDB.LinqToDBException: 'Expression '(x.Modified == value(vv.x+<>c__DisplayClass25_1).lastPostDate)' is not an association.'
How can I do this?
I used the FirstOrDefault option to get one value, but I do not understand about Expression is not an association.
Your use of the "LoadWith" method is suspicious here.
LoadWith is a specialized function to load additional table data that is linked (e.g. via foreign key) to the current table row.
Based on your usage, it looks like you're just trying to set up another "Where" clause, so instead of
.LoadWith(x => x.Modified == lastPostDate);
you wanted
.Where(x => x.Modified == lastPostDate);
or alternatively, combine this with your prior Where statement to simplify things:
var test = db.GetTable<nnn>().Where(x => x.Modified == lastPostDate &&
xguy.Distinct().Contains(x.SID));
Let me know if this isn't what you intended. If this is the case, perhaps you have an SQL statement or similar that you are now trying to translate to C# LINQ, or can otherwise explain in plain English what this statement was meant to accomplish?

Sitecore: efficient way to use LINQ to compare against an ID

I have a LINQ query retrieving a list of , such as this:
var results = SearchContext.GetQueryable<Person>()
.Where(i => i.Enabled)
.Where(i => i.TemplateName == "Person")
.Random(6);
Each object of type "Person" has a "Location" field which is also a Glass mapped item, and hence has an ID; I would like to only select items whose Location has a specific ID.
How can I go about doing this in an efficient manner?
EDIT: I should probably clarify that I am unable to perform this comparison, efficiently or not. Because the GUID is an object and I cannot perform ToString in a LINQ query, I am unable to only pick the items whose Location item has a specific ID. Any clues on how this could be achieved?
EDIT 2: Adding the clause
.Where(i => i.Location.Id == this.Id)
Doesn't work, for... some reason, as I'm unable to debug what LINQ "sees". If I convert the other ID I'm comparing it against to string this way:
var theOtherID = this.Id.ToString("N");
Then it works with this LINQ line:
.Where(i => i["Location"].Contains(theOtherID))
I still have no idea why.
One approach is to include a separate property on Person that is ignored by Glass mapper, but can be used in searches:
[SitecoreIgnore]
[Sitecore.ContentSearch.IndexField("location")]
public Sitecore.Data.ID LocationID { get; set; }
You can use this in your search as follows:
Sitecore.Data.ID locationId = Sitecore.Data.ID.Parse(stringOrGuid);
var results = SearchContext.GetQueryable<Person>()
.Where(i => i.Enabled)
.Where(i => i.TemplateName == "Person")
.Where(i => i.LocationID == locationId)
.Random(6);
I think the efficiency of using multiple where clauses vs. conditionals is debatable. They will likely result in the same Lucene query being performed. I would prefer readability over optimization in this instance, but that's just me.
I can't think of a more efficient methods than using a simple where statement like in:
var results = SearchContext.GetQueryable<Person>()
.Where(i => i.Enabled && i.TemplateName == "Person" &&
i.Location != null && i.Location.Id == 1)
.Random(6);
Keep in mind that if you use the && statement instead of a where for each parameter, you reduce the complexity of the algorithm.
You could also use an Inverse Navigation Property on Location to a virtual ICollection<Person> and then be able to do this:
var results = SearchContext.GetQueryable<Location>()
.Where(i => i.Id == 1 && i.Persons.Where(p => p.Enabled && p.TemplateName == "Person").Any())
.Random(6);
The first option would still be the most efficient, because the second one uses sub-queries. But it is worth knowing you can do your search the other way.

Multiple LINQ expressions, and dynamic properties

1.) I have an entity query like: return myEntityStore.Query<theType>(x => x.Name == "whatevs");
However, ideally I want to call a function which appends other expressions to the original query, like OrderBy's and more Where's.
Something like this:
public IQueryable<T> ProcessQuery<T>(System.Linq.Expressions.Expression<Func<T, bool>> theOriginalQuery) where T: class
{
return EntityStore.Query<T>(theOriginalQuery).Where(x => x.Active == true).OrderBy(x => x.OrderBy);
}
2.) One of the obvious problems here is that I'm working with <T>, so is there a way to specify the property as a string or something?
<T>(expression).OrderBy(x => "x.ThisColumnExistsIPromise");
3.) The Query function already transforms the expression into a Where(), so would it be sufficient to simply do a Where(expression).Where(expression)?
So, at the end of the day, is the below possible to achieve?
entityStore.Query<T>(originalExpression).Where(additionalExpression).Where(x => "x.Active == true").OrderBy(x => "x.OrderBy");
Actually the question isn't so clear. But I noticed that your problem might be solved if you used LINQ Dynamic Query Library then you could use Property name as string to do whatever you want (OrderBy, Where ....)
For more information look at this

Checking if a string is in an ObservableCollection of Tuple

I have an ObservableCollection as shown below:
ObservableCollection<Tuple<Guid, string>> _taskCollection
I want to write some code that will check if a given string exists in the collection. The string is held in “TaskName” and the code I wrote looks like this:
_taskCollection.Select(x => x.Item2 == TaskName.Trim()).Any()
The problem I have is that this line of code always returns “true” regardless of whether the value in “TaskName” is in one of the Tuple’s or not. Can anyone show me what I am missing?
You should use Any directly rather than after Select:
_taskCollection.Any(x => x.Item2 == TaskName.Trim())
This code:
_taskCollection.Select(x => x.Item2 == TaskName.Trim())
will return a list of bool which has length equivalent with _taskCollection, so then you call Any, it's always true
Select transforms N input items into N output items. The amount of items doesn't change here.
What you want is to filter the items. That's what Where is for.
Using Where your second query would have been correct:
_taskCollection.Where(x => x.Item2 == TaskName.Trim()).Any();
That can be shortened to the following:
_taskCollection.Any(x => x.Item2 == TaskName.Trim());
The reason is that Any provides an overload that accepts a condition.
And I think it really reads intuitivly: "Is there Any item in _taskCollection for which Item2 == TaskName.Trim()?"

how do I return a filtered list using linq?

I'm not sure if my title is correct, but linq should pull the right experts in to help the title and answer the question.
If I have a list of People, how do I return a list of PeopleWrappers minus "Dave" and "Jane"?
query looks like this right now:
List<Person> People = CreatListofPersons();
People.Select(t => new PeopleWrapper(t)).ToArray();
People.Where( x => x.Name!="Dave" && x.Name!="Jane")
.Select(t => new PeopleWrapper(t))
.ToArray();
LINQ has a list of extension methods that allow you to filter or project (which you already to with Select()). In your case you can use Where() to specify which elements you want to let pass, in your example all persons whose name is neither Dave nor Jane.
does it matter if "Where" comes before
"Select" or after?
You typically want to filter as soon as you can, otherwise you will have to iterate and/or project over items you don't want to have anyway.
Conceptually though, yes, you can put there where() filter later but in your case you are dealing with a PeopleWrapper after you project with Select() - since the Where() extension method is using this data type as input its condition I don't think it would make much sense - you would filter people wrappers, not persons.
return People.Where(p => p.Name != "Dave" && p.Name != "Jane");
You can use Where to get just the elements that match a condition:
People.Where(p => p.name != "Dave" && p.name != "Jane" ).Select(t => new PeopleWrapper(t)).ToArray()

Categories

Resources