Reputation: 103
I have a list of companies named Companies
which has duplicate companies inside.
Another list relationRepo
which keeps all relations between companies
and persons
.
I need all relations of companies inside Companies
.
var relations = relationRepo.Where(x => Companies.Any(y => x.QId == y.QId));
returns relations for companies but not for duplicates. In other words, for duplicate companies this query returns relations once. For example, Company A
exists in Companies
twice and there is 3 relations for Company A
in relationRepo
.
After running query above, there is 3 relations in relations
for Company A
but I need 6 relations.
Any help?
Upvotes: 0
Views: 69
Reputation: 30454
So you have Companies
, and every Company
has zero or more Relations
. Every Relation
belongs to exactly one Company
, using a foreign key CompanyId
.
Your requirement is a bit unclear:
I need all relations of companies inside Companies.
It is a bit unclear what you want.
Company (1) with Name "Acme" has Relations A, B, C
Company (2) with Name "Acme" has Relations C, X, Y
Company (3) with Name "Other" has Relations D, E,
Company (4) with Name "Other" has Relations D, F,
All Relations of all Companies inside your sequence of Companies is A B C D E X Y. Or in other words: all Relations that are used by any of the companies. According to your example, this is not what you want.
You also wrote:
I have a sequence of Companies, which has duplicate companies inside.
Apparently you have a method to decide whether two Companies are in fact the same Company. This might be by name, or by tax number, or whatever. How you decide whether two Companies are the same is irrelevant of this question. Let's assume you have an object of a class that implements IEqualityComparer<Company>
:
IEqualityComparer<Company> comparer = ...;
Back to your requirement.
I think you meant to say that you wanted Companies
with their Relations
. If two companies are in fact the same company you want them returned as one "Company with its relations"
So in the above example, you want the following result
The problem with this requirement is, if you consider two companies to be equal (for instance, because they have the same name) what do you want with the Company properties that are different? For example: What Id should I use for the Company with Name "Acme"?
Several solutions:
Because of this incomplete requirement the answer must be very generic. All answers will do the following:
The difference in the four possible requirements described above is what Company parts you select at the end.
I'll give the solution of the most likely requirement:
.
// "I have a List of companies and a List of their Relations"
IEnumerable<Company> companies = ...
IEnumerable<Relation> relations = ...
// I want all Companies with their Relations
var result = companies.GroupJoin(relations, // GroupJoin Companies and Relations
company => company.Id, // from each Company take the primary key
relation => relation.CompanyId, // from each Relation take the foreign key
// and all Relations with matching foreign key
(company, relationsOfThisCompany) => new
{
Company = company,
Relations = relationsOfThisCompany,
})
// Result: a sequence of companies, each with their Relations
.GroupBy(
// KeySelector: make groups of companies with same Name
joinResult => joinResult.Company.Name,
// ResultSelector: take the Key (which is the common Name)
// with all joinResults of companies with name equal equal to the Key to create the output
(companyName, companiesWithThisName => new
{
Name = key.Name,
Relations = companiesWithThisName.Select(company => company.Relations),
},
// Comparer: when are two company names equal?
StringComparer.CurrentCultureIgnoreCase);
Because I had a fairly simple definition of Company Equality, I could use an already existing equality comparer to decide whether two companies are equal.
The advantage of a separate comparer for company equality would be that if in future you decide that you need other properties to decide whether two companies are equal, for instance their Tax Number, instead of their name, this code won't change. It's up to you to decide whether you'll use the concept of "company equality" often enough to decide whether or not to make a special equality comparer
Upvotes: 0
Reputation: 62488
You need a join query to get what you are looking for. The following should work:
var relations = (from relation in relationRepo
join company in Companies on relation.QId equals company.QId
select relation).ToList();
This will now provide the items matching on QId
in both. What the above query does is match row in Companies
for for QId
so in your case if the Companies
have 6 items with QId
matching in relationRepo
, it will give you 6 rows for in relations
.
Upvotes: 4