I was trying to select a list of entities using EF and Linq and I should retrieve only those that has a specific AccountId inside the Participants ICollection
public class Conversation
{
public Conversation()
{
Participants = new List<Account>();
Messages = new List<Message>();
}
[Key]
public Int32 conversationId { get; set; }
public ICollection<Message> Messages { get; set; }
public ICollection<Account> Participants { get; set; }
}
_Db is DbContext
public async Task<List<Conversation>> FindByAccountIdAsync(Int32 id)
{
return await _Db.Conversations.Where(....).ToListAsync();
// .... select conversations where id == AccountId inside ICollection<Account> Participants
}
I have no idea on how to compose the query in LINQ
Use Any:
return await _Db.Conversations
.Where(c => c.Participants.Any(p => p.Id == id))
.AsQueryable()
.ToListAsync();
Related
I have different roles and each user can have multiple roles. Each role is connected to customer record in different way, e.g. a business analyst has many-to-many relation to project and each customer has many projects; whereas a customer record can have only one project manager associated to it.
public class Customer
{
public CustomerProjectManager ProjectManager { get; set; }
public ICollection<Project> Projects{ get; set; }
...
}
public class Project
{
public ICollection<ProjectBusinessAnalyst> BusinessAnalysts { get; set; }
public ICollection<ProjectDeveloper> ProjectDevelopers { get; set; }
...
}
public class ProjectDeveloper
{
public int Id { get; set; }
public Project Project{ get; set; }
public int ProjectId { get; set; }
public string DeveloperId { get; set; }
public string DeveloperEmail { get; set; }
public string DeveloperName { get; set; }
}
public class CustomerProjectManager
{
public int Id { get; set; }
public ICollection<Customer> Customers { get; set; }
public string ProjectManagerId { get; set; }
public string ProjectManagerEmail { get; set; }
public string ProjectManagerName { get; set; }
public CustomerProjectManager()
{
Customers = new List<Customer>();
}
}
I need to fetch customer records on basis of roles. To explain further, I need to combine multiple customer lists fetched on the basis of different roles assigned to a single user. I am unable to form right linq query.
I have a sample query, mentioned below, which sometimes returns the right records but if I have a new user and no customers are assigned to this user, the query returns all existing customers. Its important for me that all the combination and filtration is done in Iqueryable
Please help!
public async Task<List<Customer>> FetchCustomers(string userId, List<string> userRoles, string userEmail)
{
if (userRoles.Contains("Admin"))
{
customer = _context.Customers;
}
else if (userRoles.Contains("Project Manager") ||
userRoles.Contains("Business Analyst") ||
userRoles.Contains("Developer"))
{
if (userRoles.Contains("Project Manager"))
{
customers = customers.Where(c => c.ProjectManager.ProjectManagerId == userId
|| c.Projects.Any(op =>
op.ProjectsCompleted.Any(assignee =>
assignee.UserId == userId)));
}
if (userRoles.Contains("Business Analyst"))
{
var allPossibleCustomers = _context.Customers.Where(c =>
c.Projects.Any(op => op.BusinessAnalysts.Any(ba => ba.BusinessAnalystId == userId)));
customers = customers?.Union(allPossibleCustomers) ?? allPossibleCustomers;
}
if (userRoles.Contains(Roles.Developer.GetDescription()))
{
var allPossibleCustomers = _context.Customers.Where(c =>
c.Projects.Any(op => op.PREDevDevelopersAssigned.Any(ba => ba.DeveloperId == userId)));
customers = customers?.Union(allPossibleCustomers) ?? allPossibleCustomers;
}
}
var listData = await PagingList<Customer>.CreatePageAsync(customers, page, limit);
return listData;
}
Apparently I was trying to return the wrong list. The linq query is correct.
Im having a problem with the a LINQ query using aspnetboilerplate. despite a where clause its return all records.
I want to select all records that have an EnrolResponse.IsComplete = true.
i have three entities
public class User : Entity<int>, IFullAudited
{
public string Email { get; set; }
public List<EnrollAttemptRequest> EnrollAttempts { get; set; }
}
public class EnrollAttemptRequest : Entity<int>
{
public int UserId { get; set; }
public EnrollAttemptResponse EnrolResponse { get; set; }
}
public class EnrollAttemptResponse : Entity<int>, IFullAudited
{
public int EnrollAttemptRequestId { get; set; }
public bool IsComplete { get; set; }
}
the following query is returning all records, even if the IsComplete is equal to false.
var enroledUsers = await _userRepository.GetAll()
.Where(x => x.EnrollAttempts.Any(y=>y.EnrolResponse.IsComplete == true))
.Include(x=>x.EnrollAttempts)
.ThenInclude(x=>x.EnrolResponse)
.ToListAsync();
If breaking the query down to an IQueryable but i get the same result
Maybe you need All() instead of Any()?
If you use Any() you get all records if at least 1 satisfies the condition.
If you use All() you get all records if all satisfy the condition
var enroledUsers = await _userRepository.GetAll()
.Where(x => x.EnrollAttempts.All(y=>y.EnrolResponse.IsComplete == true))
.Include(x=>x.EnrollAttempts)
.ThenInclude(x=>x.EnrolResponse)
.ToListAsync();
I have a meetingRepository class that returns IEnumerable and an attendeeRepository class that returns IEnumerable<Attendee>
public class meetingRepository
{
IEnumerable<Meeting> GetAll()
{
//return all Meetings
}
}
public class attendeeRepository
{
IEnumerable<Attendee>GetAll()
{
//return all Attendees
}
}
public class Meeting
{
public int Id { get; set; }
public DateTime Date { get; set; }
public string FilePath { get; set; }
public int Duration { get; set; }
public IEnumerable<Attendee> Attendees { get; set; }
}
public class Attendee
{
public int Id { get; set; }
public int MeetingId { get; set; }
public string Name { get set;}
public string Role { get; set; }
}
Im struggling to come up with the link statement that will join my IEnumerable<Meeting> object with my IEnumerable<Attendee> joining each Attendee in the Attendees property of the Meeting to its related Attendee object based on the Attendee.Id
Help appreciated
Edit
#Thomas the meetingRepository I have available does not load the Attendees, it is just a full list of all Meetings (I editted to include the Id property).
So, to clarify, my meetingRepository returns an IEnumerable of a partial Meeting object (no attendees)
Id
Date
Duration
FilePath
and my attendeeRepository returns an IEnumerable of participants (editted to include MeetingId
Id
MeetingId
Name
Role
Edit
I came up with the folowing that seems to work fine
var meetingsFull = from m in meetings
join a in attendees
on m.Id equals a.MeetingId into ma
select new Meeting
{
Id=pc.Id,
Date=pc.Date,
Duration=pc.Duration,
FilePath=pc.FilePath,
Attendees=ma
};
var attendees = attendeeRepository.GetAll();
foreach(var meeting in meetingRepository.GetAll())
{
meeting.Attendees = attendees.Where(at=>at.MeetingId == meeting.Id);
}
This should do it. After these assignments your all meetings now have the attendees lists ready in them.
In an MVC4 project, using code first, I have the following:
public class Course
{
public string CourseId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public virtual Categories ICollection<Category> { get; set; }
public Course()
{
Categories = new HashSet<Category>();
}
}
public class Category
{
public string CategoryId { get; set; }
public string Name { get; set; }
public virtual Courses ICollection<Course> { get; set; }
public Category()
{
Courses = new HashSet<Course>();
}
}
Code First then rightly creates an extra table for this relation, since it is many-to-many.
My problem is when I need a list of Categories with the active Courses (IsActive==true). This here, for example, is not possible:
var categories = db.Categories.Where(x => x.Courses.Where(y => y.IsActive)).ToList();
Any input how I get a list of the categories with only the active courses?
Thanks!
This query will return all categories that have at least one course that is active:
var categories = db.Categories
.Where(x => x.Courses.Any(y => y.IsActive))
.ToList();
This query will return all categories whose courses are all active. If, for example, a category has two courses and one of the courses is inactive, that category will be excluded from the query:
var categories = db.Categories
.Where(x => x.Courses.All(y => y.IsActive))
.ToList();
I'm trying to create a single linq query which populates the following models in the CompanyViewModel constructor:
public class CompanyViewModel
{
public IList<CompanyUserViewModel> CompanyUsers { get; set; }
...
}
public class CompanyUserViewModel
{
public User User { get; set; }
public IList<UserOperationViewModel> UsersOperations { get; set; }
}
public class UserOperationViewModel
{
public Operation Operation { get; set; }
public int Permission { get; set; }
}
Currently I've got the following query:
return db.Users.Where(u => u.CompanyId == companyId)
.Select(u => new CompanyUserViewModel {
User = u,
UsersOperations = db.UsersInOperations
.Where(uo => uo.UserId == uo.UserId)
.Select(uo => new UserOperationViewModel{
Operation = uo.Operation,
Permission = uo.Permission
}).ToList()
}).ToList();
Which builds, but when the page runs I get
LINQ to Entities does not recognize the method 'System.Collections.Generic.List`1[WoodCo.Models.BusinessObject.UserOperationViewModel] ToList[UserOperationViewModel](System.Collections.Generic.IEnumerable`1[WoodCo.Models.BusinessObject.UserOperationViewModel])' method, and this method cannot be translated into a store expression.
What does one do?
Change your view model properties to use IEnumerable<T> instead of IList<T and remove the .ToList() calls.