Not functioning LINQ not in "contains" query - c#

Going nuts over this.
Simple query but its just not working.
I simply need to get the company units that are not currently assigned to any users.
IDs are GUID type.
When debugging I see that there are 2 objects in companyUnits and 1 in userCompanyUnits.
I'm trying to get that 1 companyUnit ( that doesn't exist in userCompanyunit) to show.
Instead I get no results back.
Any idea what's wrong with the query? Maybe i can't compare based on guids ?
var companyUnitsList = from x in companyUnits
where !(from c in userCompanyUnits
select c.CompanyUnit.Id).Contains(x.Id)
select x;
Thanks in advance !

Here's a way of doing it without using the Except operator, and needing a custom IEqualityComparer:
List<Tuple<int, string>> allUnits = new List<Tuple<int, string>>();
allUnits.Add(new Tuple<int, string>(1, "unit1"));
allUnits.Add(new Tuple<int, string>(2, "unit2"));
allUnits.Add(new Tuple<int, string>(3, "unit3"));
List<Tuple<int, string>> assignedUnits = new List<Tuple<int, string>>();
assignedUnits.Add(new Tuple<int, string>(2, "unit2"));
var unassigned = allUnits.Where(m => !assignedUnits.Any(asgn => asgn.Item1 == m.Item1));
//Yields unit1 and unit3
Item1 corresponds to Unit.ID

Since you have it tagged as sql, I'm assuming this is queryable's and running against the database. Depending on the ORM and whether you have navigation properties defined and usable, you could do:
var notAssigned =
from x in companyUnits
where x.Users.Any() == false
select x;
IOW, whatever navigation property or collection exists to tie the company unit to the assigned user(s) is what you would use in the query (and would most likely translate to a sql 'exists')

var list1 = from s in new String[] {"ABC1","ABC2", "ABC3", "ABC4"} select new {Field1=s,Id = Guid.NewGuid().ToString()} ;
var list2 = new String[] {"ABC3","ABC4", "ABC5", "ABC6"} ;
var requiredList = (from i1 in list1
from i2 in list2
where !i1.Field1.Contains(i2)
select i1).Distinct();

Related

joining multiple dynamic lists of objects

So I'm really trying to build dynamic reports in C# based off of multiple stored procedures across multiple databases and then join the results.
Here is an example:
List 1:
{ monthyear = '032016', submitted = '56', approved = '27'},
{ monthyear = '042016', submitted = '67', approved = '30'}
List 2
{ monthyear = '032016', returned = '17'},
{ monthyear = '042016', returned = '22'}
Knowing that the "key" column is dynamic and the results built into each list are dynamic. I am however able to retrieve a string representation of the key column that joins the lists.
The result I am looking for is:
{ monthyear = '032016', submitted = '56', approved = '27', returned = '17'},
{ monthyear = '042016', submitted = '67', approved = '30', returned = '22'}
Both list are stored as an IEnumerable<object> with an intended result of IEnumerable<object>.
Is there a way to join these, not concat, without looping?
in linq you can write the join query as this
var res = list1.Join(list2, a => a.monthyear , b => b.monthyear ,
(a, b) => new { a.monthyear,a.returned, b.submitted, b.approved});
but i`m not sure how it is implemented internally
Edit
in this case you`ll need to use reflection first (you can enhance this)
foreach (PropertyInfo p in typeof(firstObj).GetProperties())
{
foreach (PropertyInfo p2 in typeof(secondObject).GetProperties())
if (p.Name == p2.Name)
match = p.Name;
}
now the variable match stores the key as string
list1.Join(list2, a=>a.GetType().GetProperty(match).GetValue(a,null), b => b.GetType().GetProperty(match).GetValue(b,null), (a, b) => new { a.first, a.second..... });
or
, (a,b) => new { a, b});
my guide was this and this
morever check this to select all the properties if you don`t know their names
hope this helps
Well, looping is going to be required, if for no other reason than to loop through the SP results as they come in from the database.
That aside, you could have a Dictionary<string, Dictionary<string, object>> that will hold the final result. Reflection can pull all properties out from each of the records as they come in, and drop them into a Dictionary<string, object> for each record (keyed by property name, value is property value). Then merge these dictionaries into the big Dictionary<string, Dictionary<string, object>> which is keyed by whatever property you're interested in (looks like the "monthyear" property).
Reflection might not even be necessary e.g. if you're using a DataTable then you already have programmatic access to all the record field names and values.

how to use hashtable in Linq

I am trying to use hash table in linq to fetch the key whose value is ABC.
What I have done so far:
Hashtable h=new Hashtable ();
h.Add(1 , "ABC");
h.Add(2 , "AgC");
h.Add(3 , "ABC");
h.Add(4 , "AhC");
Expected output: 1, 3 (keys having value "ABC")
ICollection c= h.Keys;
var posi= from a in c
where h[a]="ABC"
select a;
But the above query is not working and giving compile time error.
The error is:
could not find an implementation of the query pattern for source type 'System.Collections.ICollection'.
What I am doing wrong? I am new to C#. How to use Hashtable in LINQ?
You should not use non-generic HashTable to start with. Use generic Dictionary<int, string> instead:
var d = new Dictionary<int, string>();
d.Add(1 , "ABC");
d.Add(2 , "AgC");
d.Add(3 , "ABC");
d.Add(4 , "AhC");
var posi = from a in d
where a.Value == "ABC"
select a.Key;
Use a Dictionary<int, string> instead of a Hashtable (see here for why) then do the following:
var dist = new Dictionary<int, string>();
dist.Add(1 , "ABC");
dist.Add(2 , "AgC");
dist.Add(3 , "ABC");
dist.Add(4 , "AhC");
var keys = dist.Where(d=> d.Value == "ABC").Select(d=> d.Key);
But If you want Hastable, Then please take a look this link
link 1
link 2
But My opinion is, Please use Dictionary .
Because Dictionary is a generic collections, And It's are a lot faster as there's no boxing/unboxing.
If you really want to use that HashTable instead of the Dictionary you can do the following:
var posi = from a in c.Cast<int>()
where h[a] == "ABC"
select a;
You just need to do this to get position:
int indexOf ( object s, Hashtable h )
{
foreach ( DictionaryEntry e in h )
if ( e.Value.Equals(s) )
return (int)e.Key;
return -1;
}
and call it like this:
var posi = indexOf("ABC", yourHashTable);
but it is true that using Dictionary would be much easier.

LINQ GroupBy extremely slow

The following code takes 5 minutes to run on 100,000 rows. That seems crazy to me. What am I doing wrong?
var query =
from foo in fooStuff.AsEnumerable()
group foo by foo.Field<Int64>("FooID") into g
select new
{
FooID = g.Key,
FooTier = g.Min(foo => foo.Field<int>("Tier"))
};
Note: On Mono.
You are materializing all the entities when you call AsEnumerable(), so your grouping is being done in memory. Try removing that part so that the grouping is done at the database level:
var query =
from foo in fooStuff
group foo by foo.FooID into g
select new
{
FooID = g.Key,
FooTier = g.Min(foo => foo.Tier)
};
It is not a direct comparision and isn't on Mono, but I have some code which does something similar with a 6MB xml file which I read into a DataSet and it has 30,000 rows and takes 0.5 seconds, so I don't think it is the groupby itself that causes the problem.
To diagnose further, I would suggest
Testing how long it takes to read the information into a list, ie
var fooList = fooStuff.AsEnumerable().ToList();
Testing how long it takes if you change the query to use fooList instead of fooStuff
Testing how long it takes if you remove FooTier = g.Min(foo => foo.Tier) from the select
Separate the .Field<> reflection from the groupby and time each section, ie first read the information from the datatable into a list , eg
var list2 =
(from foo in fooStuff.AsEnumerable()
select new {
FooID = foo.Field<Int64>("FooID")
Tier = foo.Field<int>("Tier")
}).ToList();
Then you can query this list
var query =
from foo in list2
group foo by foo.FooID into g
select new
{
FooID = g.Key,
FooTier = g.Min(foo => foo.Tier)
};
var results = query.ToList();
If this query is slow, it would suggest that there is something wrong with mono's implementation of GroupBy. You might be able to verify that by using something like this
public static Dictionary<TKey, List<TSrc>> TestGroupBy<TSrc, TKey>
(this IEnumerable<TSrc> src, Func<TSrc,TKey> groupFunc)
{
var dict= new Dictionary<TKey, List<TSrc>>();
foreach (TSrc s in src)
{
TKey key = groupFunc(s);
List<TSrc> list ;
if (!dict.TryGetValue(key, out list))
{
list = new List<TSrc>();
dict.Add(key, list);
}
list.Add(s);
}
return dict;
}
And to use it
var results = list2.TestGroupBy(r=>r.FooID)
.Select(r=> new { FooID = r.Key, FooTier = r.Value.Min(r1=>r1.Tier)} );
Note, this is not meant as a replacement for groupby and does not cope with null keys but should be enough to determine if their is a problem with groupby (assuming mono's implementation of Dictionary and List are ok).

c# Linq differed execution challenge - help needed in creating 3 different lists

I am trying to create 3 different lists (1,2,3) from 2 existing lists (A,B).
The 3 lists need to identify the following relationships.
List 1 - the items that are in list A and not in list B
List 2 - the items that are in list B and not in list A
List 3 - the items that are in both lists.
I then want to join all the lists together into one list.
My problem is that I want to identify the differences by adding an enum identifying the relationship to the items of each list. But by adding the Enum the Except Linq function does not identify the fact (obviously) that the lists are the same. Because the Linq queries are differed I can not resolve this by changing the order of my statements ie. identify the the lists and then add the Enums.
This is the code that I have got to (Doesn't work properly)
There might be a better approach.
List<ManufactorListItem> manufactorItemList =
manufactorRepository.GetManufactorList();
// Get the Manufactors from the Families repository
List<ManufactorListItem> familyManufactorList =
this.familyRepository.GetManufactorList(familyGuid);
// Identify Manufactors that are only found in the Manufactor Repository
List<ManufactorListItem> inManufactorsOnly =
manufactorItemList.Except(familyManufactorList).ToList();
// Mark them as (Parent Only)
foreach (ManufactorListItem manOnly in inManufactorsOnly) {
manOnly.InheritanceState = EnumInheritanceState.InParent;
}
// Identify Manufactors that are only found in the Family Repository
List<ManufactorListItem> inFamiliesOnly =
familyManufactorList.Except(manufactorItemList).ToList();
// Mark them as (Child Only)
foreach (ManufactorListItem famOnly in inFamiliesOnly) {
famOnly.InheritanceState = EnumInheritanceState.InChild;
}
// Identify Manufactors that are found in both Repositories
List<ManufactorListItem> sameList =
manufactorItemList.Intersect(familyManufactorList).ToList();
// Mark them Accordingly
foreach (ManufactorListItem same in sameList) {
same.InheritanceState = EnumInheritanceState.InBoth;
}
// Create an output List
List<ManufactorListItem> manufactors = new List<ManufactorListItem>();
// Join all of the lists together.
manufactors = sameList.Union(inManufactorsOnly).
Union(inFamiliesOnly).ToList();
Any ideas hot to get around this?
Thanks in advance
You can make it much simplier:
List<ManufactorListItem> manufactorItemList = ...;
List<ManufactorListItem> familyManufactorList = ...;
var allItems = manufactorItemList.ToDictionary(i => i, i => InheritanceState.InParent);
foreach (var familyManufactor in familyManufactorList)
{
allItems[familyManufactor] = allItems.ContainsKey(familyManufactor) ?
InheritanceState.InBoth :
InheritanceState.InChild;
}
//that's all, now we can get any subset items:
var inFamiliesOnly = allItems.Where(p => p.Value == InheritanceState.InChild).Select(p => p.Key);
var inManufactorsOnly = allItems.Where(p => p.Value == InheritanceState.InParent).Select(p => p.Key);
var allManufactors = allItems.Keys;
This seems like the simplest way to me:
(I'm using the following Enum for simplicity:
public enum ContainedIn
{
AOnly,
BOnly,
Both
}
)
var la = new List<int> {1, 2, 3};
var lb = new List<int> {2, 3, 4};
var l1 = la.Except(lb)
.Select(i => new Tuple<int, ContainedIn>(i, ContainedIn.AOnly));
var l2 = lb.Except(la)
.Select(i => new Tuple<int, ContainedIn>(i, ContainedIn.BOnly));
var l3 = la.Intersect(lb)
.Select(i => new Tuple<int, ContainedIn>(i, ContainedIn.Both));
var combined = l1.Union(l2).Union(l3);
So long as you have access to the Tuple<T1, T2> class (I think it's a .NET 4 addition).
If the problem is with the Except() statement, then I suggest you use the 3 parameter override of Except in order to provide a custom IEqualityComparer<ManufactorListItem> compare which tests the appropriate ManufactorListItem fields, but not the InheritanceState.
e.g. your equality comparer might look like:
public class ManufactorComparer : IEqualityComparer<ManufactorListItem> {
public bool Equals(ManufactorListItem x, ManufactorListItem y) {
// you need to write a method here that tests all the fields except InheritanceState
}
public int GetHashCode(ManufactorListItem obj) {
// you need to write a simple hash code generator here using any/all the fields except InheritanceState
}
}
and then you would call this using code a bit like
// Identify Manufactors that are only found in the Manufactor Repository
List<ManufactorListItem> inManufactorsOnly =
manufactorItemList.Except(familyManufactorList, new ManufactorComparer()).ToList();

Join two dictionaries using a common key

I am trying to join two Dictionary collections together based on a common lookup value.
var idList = new Dictionary<int, int>();
idList.Add(1, 1);
idList.Add(3, 3);
idList.Add(5, 5);
var lookupList = new Dictionary<int, int>();
lookupList.Add(1, 1000);
lookupList.Add(2, 1001);
lookupList.Add(3, 1002);
lookupList.Add(4, 1003);
lookupList.Add(5, 1004);
lookupList.Add(6, 1005);
lookupList.Add(7, 1006);
// Something like this:
var q = from id in idList.Keys
join entry in lookupList on entry.Key equals id
select entry.Value;
The Linq statement above is only an example and does not compile. For each entry in the idList, pull the value from the lookupList based on matching Keys.
The result should be a list of Values from lookupList (1000, 1002, 1004).
What’s the easiest way to do this using Linq?
from id in idList.Keys
where lookupList.ContainsKey(id)
let value1 = idList[id]
let value2 = lookupList[id]
select new {id, value1, value2}
Or, more classically
from kvp1 in idList
join kvp2 in lookupList on kvp1.Key equals kvp2.Key
select new {key = kvp1.Key, value1 = kvp1.Value, value2 = kvp2.Value}
The mistake in your query is one of scoping:
from a in theAs
join b in theBs on (leftside) equals (rightside)
a is in scope in the leftside area. b is in scope in the rightside area.
I apologize if I misinterpretted your question, but do you just want to retrieve the Values from list B only where list A has a KeyValuePair with the same Key?
from lookup in lookupList
where idList.Keys.Contains(lookup.Key)
select lookup.Value;
var q = from id in idList
join entry in lookupList
on id.Key equals entry.Key
select entry.Value;
Your desired linq statement will look like that, ID and Entry needed to be switched around on the condition.
What do you think of this ?
var values = idList.Keys.Select(i => lookupList[i]);

Categories