How to transfer 2 Enumerable collections to 1 ObservableCollectionsList? - c#

This is a complete Newbie question and I understand but how do I transfer these two distinct Enumerable collections to a single ObservableCollections?
var distinctLine1 = (from z in list
orderby z.ItemLine1
select z.ItemLine1).Distinct();
var distinctLine2 = (from z in list
orderby z.ItemLine2
select z.ItemLine2).Distinct();
foreach (var item in distinctLine1)
{
}
Sorry did change ObservableCollectionsList to ObservableCollections
ItemLine1 and ItemLine2 are both strings

I suppose you could probabl also call Distinct on union to exclude possible duplicates.
var union = distinctLine1.Union(distinctLine2).Distinct();
Or just
var union = distinctLine1.Union(distinctLine2);
And then simply create the target collection with ObservableCollection Constructor (IEnumerable):
var result = new ObservableCollection<string>(union);

Related

Filter items from database based on a List<>

I have a method that accepts two List<int> for which I need to get data from the database based on the List<>s.
So, I receive a List<PersonId> and List<NationalityId> for example, and I need to get a result set where records match the PersonIds and NationalistIds.
public List<PersonDTO> SearchPeople(List<int> persons, Lisy<int> nationalities)
{
var results = (from c in myDbContect.People where .... select c).ToList();
}
Note that I think Lists might be null.
Is there an efficient way?
I was going to try:
where ((persons != null && persons.Count > 0) && persons persons.Contains(x=>x.PersonId))
But this would generate rather inefficient SQL, and as I add more search parameters, the linq may get very messy.
Is there an efficient way to achieve this?
The join method may be easy to read, but the issue I face is that IF the input list is empty, then it shouldn't filter. That is, if nationalities is empty, don't filter any out:
var results = (from c in entities.Persons
join p in persons on c.PersonId equals b
join n in nationalities on c.NationalityId equals n
equals n
select c).ToList();
This would return no results if any of the lists were empty. Which, is bad.
If you join an IQueryable with an IEnumerable (in this case, entities.Persons and persons), your filtering will not happen within your query. Instead, your IQueryable is enumerated, retrieving all of your records from the database, while the join is performed in memory using the IEnumerable join method.
To perform your filtering against a list within your query, there are two main options:
Join using an IQueryable on both sides. This might be possible if your list of ids comes from the execution of another query, in which case you can use the underlying query in your join instead of the resulting set of ids.
Use the contains operator against your list. This is only possible with small lists, because each additional id requires its own query parameter. If you have many ids, you can possibly extend this approach with batching.
If you want to skip filtering when the list is empty, then you might consider using the extension method invocation instead of the LINQ syntax. This allows you to use an if statement:
IQueryable<Person> persons = entities.persons;
List<int> personIds = new List<int>();
if(personIds.Count > 0)
{
persons = persons.Where(p => personIds.Contains(p.PersonId));
}
var results = persons.ToList();
Note that the Where predicate uses option #2 above, and is only applied if there are any ids in the collection.
If you want to get all the records for persons for example if the list is empty and then filter by nationalityId list if its not empty you can do something like this:
List<int> personsIds = ...;
List<int> nationalitiesIds = ...;
var results = (from c in entities.Persons
join p in persons on c.PersonId equals b
join n in nationalities on c.NationalityId equals n
where ((personsIds == null || personsIds.Contains(p.Id))
&& (nationalitiesIds == null || nationalitiesIds.Contains(n.Id))
select c).ToList();

Linq query for updating list of objects with some data from another list of objects

I have list of two objects:
IList<DetailsObject>
and
IList<UpdatesObject> containing updates.
Common distinct field in both objects is ID, and UpdatesObject field is just a subset of all DetailsObject fields.
Can I use Linq method to update DetailsObject with values from UpdatesObject. I know the easiest solution would be to iterate over UpdatesObject and in each iteration find object where IDs match, and then update what is necessary.
foreach(UpdatesObject uobj in IList<UpdatesObject>)
{
foreach(DetailsObject dobj in IList<DetailsObject>)
{
if (uobj.ID == dobj.ID)
{
dobj.Detail1 = uobj.Detail1;
dobj.Detail2 = uobj.Detail2;
}
}
}
Is it possible to achieve it without such a nested loop?
You can join two lists based on ID column then use a foreach loop to update your objects:
var objects = from u in UpdatesObject
join d in DetailsObject on u.ID equals d.ID
select new { Update = u, Detail = d };
foreach(var obj in objects)
{
obj.Detail.Detail1 = obj.Update.Detail1;
obj.Detail.Detail2 = obj.Update.Detail2;
}

Compare id's of objects in two lists and get the list of objects that includes objects with ids occurring in both of them

I have struggled with it for a long time. I have two collections: MyRepository.All and MyCollection, both holds the collection of objects which has ID property. I need to get result of list of objects from MyRepository.All what contains only objects which id's are equal to MyCollection's objects'ids.
ICollection MyCollection // as parameter to method
var result = MyRepository.All.Where(r=>r.id==MyCollection.???.id).ToList();
i need to replace ??? with some linq to get this done.
ive tried different where and select caluses, excist and intersect and so on..
from a in MyRepository.All
join m in MyCollection on a.Id equals m.Id
select a
Cache the ids of MyCollection into a HashSet.
Than you can retrieve your result with a Where clause like this :
var myIdSets = new HashSet(MyCollection.Select(c => c.Id));
var result = MyRepository.All.Where(r=> myIdSets.Contains(r.id)).ToList();
var result = (from r in MyRepository.All
join r2 in MyCollection on r.id equals r2.id
select r).ToList();
MyRepository.All.Where(r=>MyCollection.Select(a=>a.id).Contains(r.id))
Linq has an .Intersect that should get you want you need.
Something like this:
var result = MyRepository.Intersect(MyCollection).ToList();
More info:
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.intersect.aspx

Select multiple where on same column

Given the following code:
var filtered = (from a in lijst select a);
foreach (string brandstof in checkedListBoxHoofdbrandstof.CheckedItems)
{
MessageBox.Show(brandstof);
filtered = (from a in lijst where a.Hoofdbrandstof.Contains(brandstof) select a);
}
MessageBox.Show(filtered.Count().ToString());
lijst is a List of a class , with about 16000 items
When checkedListBoxHoofdbrandstof.CheckedItems contains more than 1 item, the query only uses the results from the last where-clause.
For example: I have 2 values, A and B, and despite the fact that A returns 100 rows, and B returns 50 rows, only the last 50 rows are included as a result. A is not included in the results anymore.
I tried using a.Hoofdbrandstof.Any, but that results in an error about types. I also tried a.Hoofdbrandstof.Equals, with the same results.
Does anyone know how I can combine these results, so that both the results from A and B are in var filtered?
The simple way:
var checkedItems = checkedListBoxHoofdbrandstof.CheckedItems;
var filtered = from a in lijst
where checkedItems.Contains(a.Hoofdbrandstof)
select a
But complexity of this method if O(n^2) to reduce it to O(n) use a Join operation
var checkedItems = checkedListBoxHoofdbrandstof.CheckedItems.Cast<string>().ToList();
var filtered = from a in lijst
join checkedItem in checkedItems on a.Hoofdbrandstof equals checkedItem
select a

Splitting Linq List by grouping

for reporting purposes i wanna split a list of purchase orders into multiple lists. One list for each purchase address. I know it's possible to group the list by purchase address, but my question is how to split the list by this purchase address into multiple lists and use these multiple list to create individual reporting files.
code:
(from o in orders
group o by new {field1, field2, field3, field4} into og
orderby og.Key.field1
select new ViewClass
{
purchaseAddress = og.Key.field1,
product = og.key.field2,
count = og.count
}).ToList()
question: how to split above list into multiple lists for each purchaseAddress?
There's a built-in function that I think does what you want. If I assume that your code is assigned to a variable called query then you can write this:
ILookup<string, ViewClass> queryLists = query.ToLookup(x => x.purchaseAddress);
This essentially creates a list of lists that you access like a dictionary, except that each value is a list of zero or more values. Something like:
IEnumerable<ViewClass> someList = queryLists["Some Address"];
Just turn each group into a List.
select new ViewClass
{
purchaseAddress = og.Key.field1,
product = og.key.field2,
count = og.count,
List = og.ToList()
}).ToList();
Oh, your grouping is one way for entities and another way for pages... just regroup.
List<ViewClass> classes = (
from o in orders
group o by new {field1, field2, field3, field4} into og
orderby og.Key.field1
select new ViewClass
{
purchaseAddress = og.Key.field1,
product = og.key.field2,
count = og.count
}).ToList();
List<List<ViewClass>> regrouped = (
from c in classes
group c by c.purchaseAddress into g
select g.ToList()
).ToList();
Another simple built-in function that you can use is the GroupBy function. It does a similar job as the ToLookup but it means that your new list is IQuerable, not like a dictionary and a few other things (see this article for a good breakdown)
var newList = orders.GroupBy(x => x.field1);
This will return a list of lists grouped by the field(s) you specify.

Categories

Resources