remove the value in a list based on the condition - c#

I need to remove a particular value from the list based on the condition
skillResult.Where(search =>
resrictedskills.Any(resrictedskill =>
search.L5_Id.ToString() == resrictedskill.CRTS_SKILLID.ToString()
&& resrictedskill.CRTS_SKILLTYPE.ToLower() == "primary"
)
).ToList()
.ForEach(skill => skill.isRestrictedpri = true);
I tried using remove but I am getting error "cannot convert from void to particular list model"
skillResult.Remove(
skillResult.Where(search =>
resrictedskills.Any(resrictedskill =>
search.L5_Id.ToString() == resrictedskill.CRTS_SKILLID.ToString()
&& resrictedskill.CRTS_SKILLTYPE.ToLower() == "primary"
)
).ToList()
.ForEach(skill => skill.isRestrictedpri = true)
);

Remove() expects one item and returns a bool telling whether the item was found and could be removed.
You must use RemoveAll which expects a condition and returns and int telling how many items have been removed.
Since none of the two methods return skill objects, you cannot chain the ForEach on them to set a property of the skills. Therefore, you need two statements.
skillResult.RemoveAll(skillResult => resrictedskills
.Any(restrictedSkill =>
skillResult.L5_Id == restrictedSkill.CRTS_SKILLID &&
restrictedSkill.CRTS_SKILLTYPE.ToLower() == "primary"
)
);
skillResult.ForEach(skill => skill.isRestrictedpri = true);

Related

Entity Framework filtering list within object

I'm trying to filter a collection within an object in Entity Framework. I followed this example, which makes sense.
This is my resulting query:
var filteredClientEmp = context.Clients.Include(x => x.CompanyEmployee)
.Where(c => c.HrPersonId == paId && c.CompanyEmployee.Any(e => e.EmployeeBirthday != null && e.EmpType == 2 &&
e.LeftCompany == null))
.Select(c => new
{
c,
CompanyEmployee =
c.CompanyEmployee.Where(e => e.EmployeeBirthday != null && e.EmpType == 2 &&
e.LeftCompany == null)
})
.ToList()
.Select(pro => pro.c)
.ToList();
return filteredClientEmp;
However, when I inspect the filteredClientEmp object, it contains employee's with no birthday and records where the left company value is not equal to null.
The Client object has a non virtual list of Employee:
public List<Employee> CompanyEmployee { get; set; }
Why is this filtering not working?
Include() unconditionally loads all child entities. Because you project into an anonymous type with two properties:
c: the client with all its employees
CompanyEmployee: the employees for that client to whom your conditions apply
And then continue to project only c, this c still includes all employees. You need to overwrite c's CompanyEmployee collection with the filtered collection:
.Select(p => { p.c.CompanyEmployee = p.CompanyEmployee; return p.c; })
Your problem is in:
.Select(pro => pro.c).ToList();
You are not returning the clients with the list of employees filtered in:
CompanyEmployee = c.CompanyEmployee.Where(e => e.EmployeeBirthday != null && e.EmpType == 2 && e.LeftCompany == null)
In fact that property if the anonymous type is not used at all. Instead you are returning the filtered list of all clients which:
1) Have the specified HrPersonId and
2) Have at least one employee with a birthday, an employee type of 2 and have not left the company.
To return the Clients with the filtered list your final Select should look something like:
.Select(pro => { pro.c.CompanyEmployee = pro.CompanyEmployee; return pro.c; })

Fluent nHibernate Query => QueryOver, Join, Distinct

I try to change that query to QueryOver<> to be able to do the Distinct operation yet inside the (generated sql) query
var result = (from x in Session.Query<Events>()
join o in Session.Query<Receivers>() on x.ID equals o.ID
where x.Owner.ID == 1 //the user is the owner of that Event (not null)
||
x.EVType.ID == 123 //(not null)
||
x.Receivers.Count(y => y.User.ID == 1) > 0 //the user is one of the Event Receivers
select x.StartDate)
.Distinct();
I tried something like that
Events x = null;
List<Receivers> t = null;
var result = Session.QueryOver<Events>(() => x)
.JoinAlias(() => x.Receivers, () => t)
.Where(() => x.Owner.ID == 1
||
x.EVType.ID == 123
||
t.Count(y => y.User.ID == 1) > 0)
.TransformUsing(Transformers.DistinctRootEntity)
.Select(a => a.StartDate)
.List();
but then I got the Value can not be null. Parameter name: source exception. Any ideas how can I fix that query ?
edit
thanks to the xanatos' answer, the final SQL query is correct (I used his 2nd approach):
SELECT distinct this_.StartDate as y0_
FROM Events this_
WHERE
(
this_.UserID = ?
or
this_.EventTypeID = ?
or
exists (SELECT this_0_.ID as y0_
FROM Receivers this_0_
WHERE this_0_.UserID = ?)
)
"In QueryOver, aliases are assigned using an empty variable. The variable can be declared anywhere (but should be empty/default at runtime). The compiler can then check the syntax against the variable is used correctly, but at runtime the variable is not evaluated (it's just used as a placeholder for the alias)." http://nhibernate.info/blog/2009/12/17/queryover-in-nh-3-0.html
Setting List<Receivers> t to empty collection as you did (as you have mentioned in comments) means that you check is event id in local empty collection - doesn't have sense at all.
You can try do your query with subquery (should work but i'm not sure, I wrote it without testing, "by hand"):
Receivers receiversSubQueryAlias = null;
var subquery = session.QueryOver<Events>()
.JoinQueryOver<Receivers>(x => x.Receivers, () => receiversSubqueryAlias, JoinType.Inner)
.Where(()=> receiversSubQueryAlias.UserId == 1)
.Select(x => x.Id)
.TransformUsing(Transformers.DistinctRootEntity);
Events eventsAlias = null;
var mainQueryResults = session.QueryOver<Events>(() => eventsAilas)
.Where(Restrictions.Disjunction()
.Add(() => eventAlias.OwnerId == 1)
.Add(() => eventAlias.EVType.Id == 123)
.Add(Subqueries.WhereProperty<Events>(() => eventAlias.Id).In(subquery))
).Select(x => x.StartDate)
.TransformUsing(Transformers.DistinctRootEntity)
.List();
As written by #fex, you can't simply do a new List<Receivers>. The problem is that you can't mix QueryOver with "LINQ" (the t.Count(...) part). The QueryOver "parser" tries to execute "locally" the t.Count(...) instead of executing it in SQL.
As written by someone else, TransformUsing(Transformers.DistinctRootEntity) is client-side. If you want to do a DISTINCT server-side you have to use Projections.Distinct .
You have to make an explicit subquery. Here there are two variants of the query. the first one is more similar to the LINQ query, the second one doesn't use the Count but uses the Exist (in LINQ you could have done the same by changing the Count(...) > 0 with a Any(...)
Note that when you use a .Select() you normally have to explicitly tell the NHibernate the type of the .List<something>()
Events x = null;
Receivers t = null;
// Similar to LINQ, with COUNT
var subquery2 = QueryOver.Of<Receivers>(() => t)
.Where(() => t.SOMETHING == x.SOMETHING) // The JOIN clause between Receivers and Events
.ToRowCountQuery();
var result2 = Session.QueryOver<Events>(() => x)
.Where(Restrictions.Disjunction()
.Add(() => x.Owner.ID == 1)
.Add(() => x.EVType.ID == 123)
.Add(Subqueries.WhereValue(0).Lt(subquery2))
)
.Select(Projections.Distinct(Projections.Property(() => x.StartDate)))
.List<DateTime>();
// With EXIST
var subquery = QueryOver.Of<Receivers>(() => t)
.Where(() => t.SOMETHING == x.SOMETHING) // The JOIN clause between Receivers and Events
.Select(t1 => t1.ID);
var result = Session.QueryOver<Events>(() => x)
.Where(Restrictions.Disjunction()
.Add(() => x.Owner.ID == 1)
.Add(() => x.EVType.ID == 123)
.Add(Subqueries.WhereExists(subquery))
)
.Select(Projections.Distinct(Projections.Property(() => x.StartDate)))
.List<DateTime>();
Note that you'll have to set "manually" the JOIN condition in the subquery.
Hopefully this answer can help others. This error was being caused by declaring
List<Receivers> t = null;
followed by the query expression
t.Count(y => y.User.ID == 1) > 0
The QueryOver documentation states "The variable can be declared anywhere (but should be empty/default at runtime)." Since in this case, the place holder is a List, you must initialize it as an empty list.
List<Receivers> t = new List<Receivers>();
Otherwise, when you try to reference the Count method, or any other method on the placeholder object, the source (t) will be null.
This however still leaves a problem as #fex and #xanatos, in which it makes no sense to reference Count() from the alias List t, as it won't convert into SQL. Instead you should be creating a subquery. See their answers for more comprehensive answer.

List where Clause with Remove

The code below works successfully to remove if a value exists in a list. How do I add a where clause such that only for list items where sType = "File"
MyGlobals.lstNewItems.RemoveAll(item => item.sItemName == rows[i].Cells[0].Value.ToString());
Pseudo Code for what i want
MyGlobals.lstNewItems.Where(y => y.sType == "File").RemoveAll(item => item.sItemName == rows[i].Cells[0].Value.ToString());
If you want to remove all of the items where both conditions are true, then simply AND them together:
MyGlobals.lstNewItems.RemoveAll(item =>
item.sItemName == rows[i].Cells[0].Value.ToString()
&& item.sType == "File");

Remove from a list where a elements value is null

I am trying to remove from a list in a list where there are null.
For Example:
responses.Questions[0].Options[0].Value = "asdf";
responses.Questions[0].Options[1].Value = null;
responses.Questions[0].Options[2].Value = 1;
I want to remove the second options in the list because the value is null. So When I am done I have a list like so:
responses.Questions[0].Options[0].Value = "asdf";
responses.Questions[0].Options[1].Value = 1;
I tried the code below but it doesn't appear to work:
responses.Questions.Select(q => q.Options.RemoveAll(o => o.Value == null));
use foreach:
foreach(var q in responses.Questions)
{
q.Options.RemoveAll(o => o.Value == null);
}
Try this
responses.Questions.ForEach(q => q.Options.RemoveAll(o => o.Value == null));
Use a Where clause in order to exclude null option lists:
responses.Questions
.Where(q => q.Options != null)
.ForEach(q => q.Options.RemoveAll(o => o.Value == null));
(According to one of your comments that is deleted now, you got an exception because of Options being null.)
Note: null values can appear at different levels here. responses, Questions, q and Options could theoretically all be null. Add tests where appropriate.

linq predicate remove objects from collection issue

I am trying to figure out why my delegate function does not work, any help would be appreciated, this is probably a small issue but I have been working on it for a while and connot figure it out, my code:
//remove all matching people from this list
public void RemovePeopleFromLookup(Predicate<PeopleDTO> _people)
{
//Lookup is an internal readonly ICollection of PeopleDTO
Lookup.RemoveAll(_people);
}
//call the method as below:
//data is a collection of PeopleDTO
mylookupobj.RemovePeopleFromLookup(x => data.Any(y => y.Name == x.Name && x.Type == FieldElement.Strange));
For some reason all people get removed from this lookup, this is not correct, I only want to remove the people who are
Strange
who DONOT exist in the data collection
EDIT:
The data collection can be an object of different types -> strange, noisy etc...
The mylookupobj.Lookup data collection is similar to the data collection and contain contain multiple types hence why I wrote my query that way
EDIT2: I missed out this information which may be very important...
public class PersonDTO
{
//Name
//Type
//Age
//Desc
}
Inside the mylookupobj.Lookup - all the properties contain data, however inside the data collection only the Name + Type is present.
A simpler and more efficient predicate would be:
x => (x.Type == FieldElement.Strange) && data.Any(y => y.Name == x.Name)
But I admit I don't see a principal problem with either.
Edit: seems 1 of the conditions has to be inverted.
x => (x.Type == FieldElement.Strange) && ! data.Any(y => y.Name == x.Name)
The call to Any is the problem. Essentially it's running through the collection multiple times. i.e. if any of the objects in the collection matches the condition, remove the item. Try this:
mylookupobj.RemoveFieldFromLookup(y => y.Name == x.Name && x.Type == FieldElement.Strange);
Please try this.
mylookupobj.RemovePeopleFromLookup(x => data.Contains(y => y.Name == x.Name)
&& x.Type == FieldElement.Strange);

Categories

Resources