Compare two list if match found update first list property - c#

I have two lists first is
DataTable DtblDiseaseList = this.GetDisease();
List<DiseaseModel> model = DtblDiseaseList.DataTableToList<DiseaseModel>();
And second is
var userDisease = DiseaseManagementBA.getUserDisease(UserID).DataTableToList<DiseaseModel>();
Here I want to compare userDisease with model list if match found then I want to update the property of first list i.e. model. In DiseaseModel class there is on property i.e. IsChecked. I want to set true to this property if match found.

The first "if match found" can be done using a Join. This enumerates each of your lists and returns the results from model in which the "match" condition is found. I am presuming there the "match" is matching IDs as I don't know the actual criteria.
var result = (from m in model
where join d in userDisease on m.ID == d.ID
select m).ToList();
Once you have the list, its a matter of iterating and setting the value. I'm sort of assuming you're using LinqToSql with the InsertOnSubmit and the SubmitChanges methods.
foreach (var r in result)
{
r.IsChecked = true;
this.InsertOnSubmit(r);
}
this.SubmitChanges();
I should note that this will work, but results from the first join are enumerated into memory, they are not updated by the database.

You could do it simply as following:
model.Intersect(userDisease).ToList().ForEach(_ => _.IsChecked = true);

Hello guys my problem is solved by this Linq query
model.Where(x => userDisease.Any(z => z.DiseaseId == x.DiseaseId)).Select(x => { x.IsChecked = true; return x; }).ToList();

Related

How to order list based on some id found in another list c#?

I know there are plenty of question about this topic but none of them seems to solve my answer (or at least from what i have found) pardon me if this is a duplicate question.
I have a list that i gather from SQL containing two properties SequenceId and Relevant:
var sequenceList = await context.SequenceDB.Where(c => c.PeopleId == peopleId).Select(c => {
SequenceId = c.SequenceId,
Relevant = c.Relevant
}).OrderBy(c => c.Relevant).ToListAsync();
Then i have another list like so:
var secondList = await context.Activity.ToListAsync();
FYI
the second list has multiple properties (hence column in the database) and one of them is SequenceId pointing to that SequenceId in SequenceDB.
What i want is to order the secondList based on the order of GUID's in the sequenceList.
BUT:
I just need to order them NOT exclude them from the list. And i don't want to exclude any of the elements from secondList
The result will be a list of Activity with as first elements the ones from sequenceList and then the rest
If you think this is a duplicate question please point me to the right one and i'll delete this one.
It seems simple even though is not for me.
You can join the lists using an outer join, so something like this should work.
First, number each row in secondList so we can retain the order for items which don't match those in the sequenceList.
var indexedSecondList = secondList.Select((e, index) => new { e, index });
(from r in indexedSecondList
join s in sequenceList on r.e.SequenceId equals s.SequenceId into tmp
from t in tmp.DefaultIfEmpty()
orderby t != null ? 0 : 1 , // Sort the entries that are in SequenceList first
t != null ? t.Relevant : (System.Guid?) null , // Then sort by Relevant
r.index // Finally sort by original order in secondList
select r.e).ToList();

How to combine two queries and get one List in mvc c#

How can I combine these two lists in one List?
public IActionResult Open(int? id)
{
var questions = (from q in _context.Questions where q.CategoryId == id select q).ToList();
var answers = (from s in _context.Answers
join b in questions
on s.QId equals b.ID
group s by b.ID into g
select g.Count()).ToList();
if (questions == null)
{
return NotFound();
}
return View(questions);
}
The problem you are facing is a common one. As already mentioned by #Arripe here, you can create a ViewModel that is a composite class with the properties from each class that you want to use in your presentation layer. With a simple search for "create viewmodel asp.net mvc" or similar, you can find a guide to creating a ViewModel. Yours might be called "QuestionAnswerViewModel".
Constructing the actual ViewModel can be clunky (loop through each collection, mapping properties as you go), or you can be more creative with it.
For example, you could try joining the two query results into a combined result list, with the results being of type .
See #JonSkeet example here: how do I join two lists using linq or lambda expressions
I think what you're trying to get is Questions with number of Answers you have for them, right? If that's the case, then I think this should be the simplest solution. Of course you'll need to update the View to work with the new object.
var questionsWithAnswerCount = _context.Questions.Where(q => q.CategoryId == id)
.GroupJoin(_context.Answers, // list you join with
q => q.ID, // "main" list key
a => a.QId, // joined list key
(q, a) => new { Question = q, AnswerCount = a.Count() } // what to do with result - create new object that has Questions & Number of answers
)
.ToList();
if (questionsWithAnswerCount.Any()) // No need to check for null since you're calling .ToList() which will return an empty list, even when no elements were found, instead call .Any() to check if the list is empty or not
{
return View(questionsWithAnswerCount);
}
return NotFound();
Use a ViewModel to store two list and pass it to the View

Linq query with multiple where's [duplicate]

This question already has answers here:
Multiple WHERE clause in Linq
(3 answers)
Closed 2 years ago.
I am trying the to query my Status Update repository using the following
var result = (from s in _dataContext.StatusUpdates
where s.Username == "friend1" && s.Username == "friend2" etc...
select s).ToList();
Instead of using s.Username == "friendN" continuously is there anyway I can pass a list or array or something like that rather that specifying each one, or can I use a foreach loop in the middle of the query.
Thanks
If you only need to check whether the Username property has some specified value, you can create a list of the values and then use method such as All or Any to check if some condition holds for any/all elements of the array.
Your example looks a bit suspicious though - the user name s.Username cannot be equal to multiple different strings. Did you want to check whether it is equal to any of the (specified) names? That could be written like this:
var friends = new[] { "friend1", "friend2", ... };
var result =
from s in dc.StatusUpdates
where friends.Any(fr => s.Username == fr)
select s;
This returns all status updates such that the Username property is equal to any of the specified friend names (specified as an array, but you could use any IEnumerable<string>).
Yo could do it like this:
IQueryable<s> query= _dataContext.StatusUpdates;
foreach (var item in names)
{
query = query.Where(p=>p.Username == item);
}
List<s> result = query.ToList();
I think I mucked with some data types of yours but this should be close:
var names = new List<string>();
// populate names
var updates = new List<StatusUpdate>();
// populate updates
var result = (from s in updates
where names.Contains(s.ToString())
select s).ToList();

Linq to update a collection with values from another collection?

I have IQueryable<someClass> baseList
and List<someOtherClass> someData
What I want to do is update attributes in some items in baseList.
For every item in someData, I want to find the corresponding item in baselist and update a property of the item.
someOtherClass.someCode == baseList.myCode
can I do some type of join with Linq and set baseList.someData += someOtherClass.DataIWantToConcantenate.
I could probably do this by iteration, but is there a fancy Linq way I can do this in just a couple lines of code?
Thanks for any tips,
~ck in San Diego
To pair elements in the two lists you can use a LINQ join:
var pairs = from d in someData
join b in baseList.AsEnumerable()
on d.someCode equals b.myCode
select new { b, d };
This will give you an enumeration of each item in someData paired with its counterpart in baseList. From there, you can concatenate in a loop:
foreach(var pair in pairs)
pair.b.SomeData += pair.d.DataIWantToConcantenate;
If you really meant set concatenation rather than +=, take a look at LINQ's Union, Intersect or Except methods.
LINQ is for querying - not for updating. That means it'll be fine to use LINQ to find the corresponding item, but for the modification you should be using iteration.
Admittedly you might want to perform some appropriate query to get baseList into an efficient form first - e.g. a Dictionary<string, SomeClass> based on the property you'll be using to find the corresponding item.
You can convert the IQueryable<SomeClass> into a List<SomeClass>, use the ForEach method to loop over it and update the elements, then convert back to IQueryable:
List<SomeClass> convertedList = baseList.ToList();
convertedList.ForEach(sc =>
{
SomeOtherClass oc = someData.First(obj => obj.SomeCode == sc.MyCode);
if (oc != null)
{
sc.SomeData += oc.DataIWantToConcatenate;
}
});
baseList = convertedList.AsQueryable(); // back to IQueryable
But it may be more efficient during this using non-LINQ constructs.
As mentioned before, it should be a combination of loop and LINQ
foreach (var someDataItem in someData)
{
someDataItem.PropertyToUpdate = (baseList.FirstOrDefault(baseListItem => baseListItem .key == someDataItem.key) ?? new SomeClass(){OtherProperty = "OptionalDefaultValue"}).OtherProperty;
}
You can't simply find objects that are in one list but not the other, because they are two different types. I'll assume you're comparing a property called OtherProperty that is common to the two different classes, and shares the same type. In that case, using nothing but Linq queries:
// update those items that match by creating a new item with an
// updated property
var updated =
from d in data
join b in baseList on d.OtherProperty equals b.OtherProperty
select new MyType()
{
PropertyToUpdate = d.PropertyToUpdate,
OtherProperty = d.OtherProperty
};
// and now add to that all the items in baseList that weren't found in data
var result =
(from b in baseList
where !updated.Select(x => x.OtherProperty).Contains(b.OtherProperty)
select b).Concat(updated);

LINQ to Entity: using Contains in the "select" portion throws unexpected error

I've got a LINQ query going against an Entity Framework object. Here's a summary of the query:
//a list of my allies
List<int> allianceMembers = new List<int>() { 1,5,10 };
//query for fleets in my area, including any allies (and mark them as such)
var fleets = from af in FleetSource
select new Fleet
{
fleetID = af.fleetID,
fleetName = af.fleetName,
isAllied = (allianceMembers.Contains(af.userID) ? true : false)
};
Basically, what I'm doing is getting a set of fleets. The allianceMembers list contains INTs of all users who are allied with me. I want to set isAllied = true if the fleet's owner is part of that list, and false otherwise.
When I do this, I am seeing an exception: "LINQ to Entities does not recognize the method 'Boolean Contains(Int32)' method"
I can understand getting this error if I had used the contains in the where portion of the query, but why would I get it in the select? By this point I would assume the query would have executed and returned the results. This little ditty of code does nothing to constrain my data at all.
Any tips on how else I can accomplish what I need to with setting the isAllied flag?
Thanks
This poached from a previous answer...
Contains not supported.
IN and JOIN are not the same operator (Filtering by IN never changes the cardinality of the query).
Instead of doing it that way use the join method. It's somewhat difficult to understand without using the query operators, but once you get it, you've got it.
var foo =
model.entitySet.Join( //Start the join
values, //Join to the list of strings
e => e.Name, // on entity.Name
value => value, //equal to the string
(ModelItem ent, String str) => ent);//select the entity
Here it is using the query operators
var foo = from e in model.entitySet
join val in values on
e.Name equals val
select e;
Basically the entity framework attempts to translate your LINQ query into a SQL statement but doesn't know how to handle the Contains.
What you can do instead is retrieve your fleets from the database and set the isAllied property later:
var fleets = (from af in FleetSource
select new Fleet
{
fleetID = af.fleetID,
fleetName = af.fleetName,
userId = af.userId
}).AsEnumerable();
foreach (var fleet in fleets)
{
fleet.isAllied = (allianceMembers.Contains(fleet.userID) ? true : false);
}
Everyone above me is wrong!!! (No offense ...) It doesn't work because you are using the IList overload of "Contains" and not the IEnumerable overload of "Contains". Simply change to:
allianceMembers.Contains<int>(af.userID)
By adding the <int>, you are telling the compiler to use the IEnumerable overload instead of the IList overload.
var fleets = from af in FleetSource;
var x = from u in fleets.ToList()
select new Fleet
{
fleetID = u.fleetID,
fleetName = u.fleetName,
isAllied = (allianceMembers.Contains(u.userID) ? true : false)
}
calling ToList() on fleets the query is executed, later you can use Contains().

Categories