How do I get like to return data from multiple tables? - linq

I'm trying to modify the following query to return data from multiple tables.
I have the main contacts table where all contact details are stored. Companies are also stored in the Contacts table. Companies are mapped to Contacts in a join table named CompanyPersonMap.
I also have an attributes table where the contacts are assigned certain attributes, possibly many per contact.
Now, I want to return all the contacts that have a certain attribute assigned PLUS the person's Company name and address found in a different row in the Contacts table.
This code works but only returns the contactId. Fine for what I needed but I can't figure out how to modify it for the above requirement.
var peopleAndAddresses = Contacts.Where(c => c.AssignedAttributes
.Any (aa => aa.AttributeID == 1153))
.Select(x => x.ContactID);
Any suggestions for doing this?
Thanks!
Edit-
I tried working on the .Select() statement and found the path from the contact to its organzation via the PersonOrgMap table. Unfortunately, I can't get any of the data about the organization. I tried .Any(), .All(), and .FirstOrDefault(). Any suggestions?
.Select (c => new {c.FirstName, c.LastName, c.PersonOrgMap.FirstOrDefault (pom => pom.ChildContactID) })

This code below will get you all Contacts that have at least one AssignedAttribute with an AttributeID of 1153. I think this is what you're looking for.
var peopleAndAddress = Contacts
.Where(c => c.AssignedAttributes.Any(aa => aa.AttributeID == 1153))
.Select(c => c);
However, your statement "name and address found in a different row in the Contacts table" makes me think that this might not be what you need. Can you just get what the Company Name and Address is from properties on Contact?

Related

.Where in LinQ not working correctly

I have Documents table and Signs table. Document record can be related with many records in Signs table.
Now, I want to get all records of Documents table when document ID appears in Signs table.
Here I get all documents:
var documents = (from c in context.documents select c);
Here I get all my signs and save into List:
var myDocuments = (from s in context.signs where s.UserId== id select s.ID).ToList();
This list contains collection on document ID.
And here, I'm trying to get all documents that exists in myDocuments list:
documents.Where(item => myDocuments.Contains(item.ID));
But, when I do .ToList() allways return all records (in database only exists one compatible record)
What is wrong in LinQ statement?
The problem is that this statement doesn't modify the contents of documents, it merely returns the results (which you're not doing anything with):
documents.Where(item => myDocuments.Contains(item.ID));
documents is still the full list.
Change this line to something like:
var matchingIDDocs = documents.Where(item => myDocuments.Contains(item.ID));
And then use matchingIDDocs in place of "documents" later in your code.

Linq SelectMany query not working

I have the following database tables where the relationship between Topic and Comment is 1:N
Category
id
name
Topic
id
title
category_id
Comment
id
details
topic_id
deleted (boolean)
I want a query to count total comments in each category. I have the following LINQ query but it doesn't work:
#foreach (var cat in Model.AllPermissionSets.Keys)
{
var commentCount = cat.Topics.Where(c => c.Comments.deleted != 0).SelectMany(x => x.Comments).Count();
#* some other stuff *#
}
In Visual studio I get error IList<Comment> doesn not contain a definition for deleted...
What's the correct syntax to do the above?
Comments is a collection type property on each Topic instance. This collection does not have a deleted property. But each item in the collection(a single instance of Comment) has it.
var commentCount = cat.Topics.Where(c => c.Comments.Any(s=>!s.deleted))
.SelectMany(x => x.Comments).Count();
This will give you the count of non deleted comments from all the posts of the category.
The first part, cat.Topics.Where(c => c.Comments.Any(s=>!s.deleted)) will give you a filtered list of Topic collection which has at least one non deleted comment. In the second part, you are selecting the Comments of All those posts and doing a Count.
Copied from Ivan Stoev's comment below.
The below query will also produce the same result, but more clean.
var commentCount =cat.Topics.SelectMany(t => t.Comments.Where(c => !c.Deleted)).Count();

How do I get unique Linq-to-Entities results when there is no primary key?

I have an entity model of an Oracle data source over which I have no control. Using this model I query a particular view to see get all volume price breaks for a given product:
As you can see, this view has no primary key. Here is the LINQ I am using:
var db = GetOracleDataContext();
var result = db.ITEMPRICEBREAKS_V.Where(p => p.STOCKNO == stockId).ToList();
This works to some degree, but instead of returning four distinct records with their own quantities and pricing, it returns four identical records, each with the pricing and quantities of the first record ($4800, 0, 2).
I have no control over this view. Is there another way I can structure my LINQ query so that I can get the four distinct values?
Select only the fields you care about and use Distinct(). For example:
var result = db.ITEMPRICEBREAKS_V
.Where(p => p.STOCKNO == stockId)
.Select(p => p.Price)
.Distinct()
.ToList();
However, I'd strongly recommend, along with the other commenters, that you get a primary key involved.

Need advice on designing an index to keep track of users that are not subscribed to a document in the system

I have a table for Projects, a table for Documents (with a FK to Projects), and a table for users with a relationship to projects and documents. Users can be subscribers to a document and that is how they have a relationship to the document.
Users are considered team members on a project. A document can only assigned to one project at a time. Only users, from the "Project Team" can be subscribed to a document.
What I am struggling with, in my application, is that admins are able to add users as subscribers to a document. However, the admin can only pick from a list of unsubscribed users. Those unsubscribed users are members of the project team, like I said above.
Right now, I am creating 2 queries on my database to pull all the subscribed users and the entire list of team members. I then compare the list and only pull the team members that are not subscribed.
I am not sure if I should even index this type of data or just pull from the database directly. If I should use an index, this data needs to be updated quickly becuase the admins need that unsubscribed list rather fast.
This is what my query looks like going against Entity Framework 4.1:
var currentSubscribers = _subscriptionRepository.Get(s => s.DocumentId == documentId).Select(s => s.Contact).ToList();
if (projecTeamMembers != null)
{
var availableSubscribers = (projecTeamMembers.Where(
p => !(currentSubscribers.Select(c => c.Id)).Contains(p.Id))).ToDictionary(c => c.Id, c=> c.LastName + ", " + c.FirstName);
return availableSubscribers;
}
else
{
return null;
}
This works great in EF, but I have been thinking of indexing my data using Lucene.Net and need some advice on if I should do this or not.
Write this query indide your data repository where you have access to the Database context
var q = from m in dbContext.ProjecTeamMembers
where !(from s in dbContext.Subscribers
where s.DocumentId == documentId &&
s.Contact.Id == p.Id
select s).Any()
select m;
var availableSubscribers = q.ToDictionary(m => m.Id, c=> m.LastName + ", " + m.FirstName);
The best way I have found to do something like this is, using Lucene.net, is to keep an index of subscribers and an index of all team members. And compare the two. It's faster than pulling form the database each time.

Concatenating lists inside a LINQ query

My data structure is set up this way
A user takes a number of modules
A module contains a number of courses
Here's how the relationship looks like:
How do I get a list of courses the user takes?
The query I have now is:
var courses = (from ClassEnrollment enrolment in entities.ClassEnrollment
where enrolment.UserID == UserID
join Module module in entities.Module
on enrolment.ModuleID equals module.ID
select module.Course
).ToList();
However, this doesn't result in a list of courses, but rather a list of list of courses.
How can I flatten this query to a list of distinct courses?
According to your data structure screenshot, you have a one-to-many relationship between the ClassEnrollment and Module, as well as navigational property called Module. You also have a many-to-many relationship between Module and Course, but the navigational property should be called Courses. Given your code, you want something like this:
var courses = entities.
ClassEnrollment.
Where(e => e.UserID == UserID).
SelectMany(e => e.Module.Courses).
ToList();
Your question, however, mentions a user: A user takes a number of modules, How do I get a list of courses the user takes?. I don't see any User entity anywhere else, though, so it would be nice if you could clarify. Are you using LINQ-to-SQL, btw?
Something like this:
var courses = from ClassEnrollment enrolment in entities.ClassEnrollment
from module in entities.Module
where enrolment.ModuleID equals module.ID && enrolment.UserID equals UserID
select module.Course
Use SelectMany.
You can use
courses.SelectMany(c => c);
In your query you don't need explicitly specify the type for the range variables
Or you can join course to the query
var query = from enrolment in entities.ClassEnrollment
join module in entities.Module on enrolment.ModuleID equals module.ID
join course in entities.Course on module.CourseID equals course.ID
where enrolment.UserID == UserID
select course;
var course = query.ToList();

Resources