How to apply this query in entity framework method syntax
select company_id, country_id from companies, departments where companies.company_id == departments.company_id and department.departmentId = 10;
So far, I have:
var company = context.companies
.Where(com => com.Departments
.Contains(context.departments
.Where(dep => dep.department_id==_user.Department)
.FirstOrDefault()
)
)
.Select(com => new { com.company_id, com.Country })
.FirstOrDefault();
Using method based syntax, this could be as simple as;
var company = context.Companies
.Where(x => x.Departments
.Any(x => x.department_id == _user.Department)
)
.Select(x => new { x.company_id, x.Country });
This assumes your tables are set up with foreign keys giving each Company a list of Department objects. It very much depends on your data structure.
Related
I am new to EF 6, then I stumble upon this query and I need to modify it to include the data from OrderDelay table. I only intend to get a single row from the database so I tried
.Include(m => m.OrderDelay.FirstOrDefault()) instead of .Include(m => m.OrderDelay). But it does not work. Any idea on how to get just a single row for this table?
var res = await _db
.Include(m => m.BusAdd)
.ThenInclude(b => b.Suburb)
.ThenInclude(s => s.State)
........
.Include(m => m.OrderDelay)
.AsNoTracking()
.SingleOrDefaultAsync(p => p.Id == id);
return res;
it does return a single row from sql the main _db.SingleOrDefaultAsync(p => p.Id == id);
if you use Include() sql-c# translation of outer join it will satisfy the main condition of the Where() and return everything that the included table is linked to.
so it will return
1 main row that satisfy the main condition of SingleOrDefaultAsync(p => p.Id == id);
multiple foreign table row
If you are pertaining to only one result _db then do not use/add multiple Include(x => x.TableName)
Just use _db.SingleOrDefaultAsync(p => p.Id == id);
But if you want to have all the Joined tables but only one of each BusAdd, Suburb, State, OrderDelay
then insert .Select() before/after SingleOrDefaultAsync() with conditions of
{
prop1 = row.prop1,
prop2 = row.prop2,
BusAdds = row.BusAdds.FirstOrDefault/SingleOrDefaultAsync(add condition here or none),
Suburbs = row.Suburbs.FirstOrDefault/SingleOrDefaultAsync(add condition here or none),
States = row.States.FirstOrDefault/SingleOrDefaultAsync(add condition here),
OrderDelay = row.OrderDelay.FirstOrDefault/SingleOrDefault(add condition here or none)
}
Utilizing MVC 5 and Entity Framework I am trying to set up my a ViewModel for my Index view for a show of Employees and their goals.
I have an employee table, an employeeMap table (join table with payload) and a goal table.
There is a one-to-many relationship between Employee and EmployeeMap and between Goal and EmployeeMap.
I am a total newbie and getting stuck with an index view, which initially should display employees, and when one employee is selected should display the goals of the employees.
I can't get my index action right:
var viewModel = new EmployeeGoals();
viewModel.Employees = db.Employees
.Include(d => d.Department)
.Include(e => e.Position)
.Include(m => m.EmployeeMaps)
.Where(d => d.OrganizationID == oid && d.Department.ManagerID == currentUser.EmployeeID)
.OrderBy(d => d.HireDate);
if (id != null)
{
ViewBag.EmployeeID = id.Value;
viewModel.EmployeeMaps = viewModel.Employees.Where(e => e.ID == id.Value).Single().EmployeeMaps;
viewModel.Goals = viewModel.EmployeeMaps.Where(e => e.EmployeeID == ViewBag.EmployeeID).Select(e => e.Goals);
}
if (goalID != null)
{
ViewBag.GoalID = goalID.Value;
viewModel.Activities = viewModel.Goals.Where(
x => x.ID == goalID).Single().Activities;
}
return View(viewModel);
I do get the viewmodel.employees populated correctly, but not the viewmodel.goals
oh, and the viewmodel is:
public class EmployeeGoals
{
public IEnumerable<EmployeeMap> EmployeeMaps { get; set; }
public IEnumerable<Employee> Employees { get; set; }
public IEnumerable<Goal> Goals { get; set; }
}
A hint to help me past this would be great.
Thanks
Got it working using a different approach:
viewModel.Employees = db.Employees
.Include(d => d.Department)
.Include(e => e.Position)
.Include(m => m.EmployeeMaps)
.Where(d => d.OrganizationID == oid && d.Department.ManagerID == currentUser.EmployeeID)
.OrderBy(d => d.HireDate);
if (id != null)
{
ViewBag.EmployeeID = id.Value;
viewModel.EmployeeMaps = viewModel.Employees.Where(e => e.ID == id.Value).Single().EmployeeMaps;
viewModel.Goals = from g in db.Goals
join m in db.EmployeeMaps on g.ID equals m.GoalID
join e in db.Employees on m.EmployeeID equals e.ID
where m.EmployeeID == id.Value
select g;
}
couldn't figure out how to get a result using navigation properties, so ended up with above solution. It does the job, but am I hitting the database too often?? Also, ended up with a mix of LINQ syntax'es - should go with just one of them, I know :-/
You should use SelectMany:
viewModel.Goals = viewModel.EmployeeMaps
.Where(e => e.EmployeeID == ViewBag.EmployeeID)
.SelectMany(e => e.Goals);
because EmployeeMaps.Where() is an IEnumerable, so a Select produces IEnumerable<IEnumerable<Goal>>. SelectMany flattens this into IEnumerable<Goal>.
I am developing an ASP.NET MVC application. I have two queries I want to get common records from those queries.
Am I suppose to write simple join to get the common records ?
var poList =
(from po in db.PurchaseOrders
where po.CompanyId == companyId &&
po.PartyId == partyId &&
(po.IsDeleted == false || po.IsDeleted == null)
select po into newPO
select new
{
Name = newPO.PONo,
Id = newPO.Id
});
var poList2 = (db.Employees.Where(x => x.Id == EmpID)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Employees)
.Distinct()
.SelectMany(x => x.PurchaseOrders)
.Select(po => new { Name = po.PONo, Id = po.Id }));
I am trying to write the join but its asking for one more argument, how to write a simple join for common records ?
var finalPO = poList.Join(poList2).ToList();
You can use an overload of Join method to specify join conditions:
poList.Join(poList2, a => a.Name, b => b.Name, (a,b) => new { Name = b.PONo, Id = b.Id });
Union will give you all records from both:
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.union.aspx
Join method will give you records that match on provided key, but requires more than just the two enumerables as parameters:
http://msdn.microsoft.com/en-us/library/bb534675.aspx
You don't need a join because you can apply the expressions in the first query to the "raw" result of the second one:
var poList2 = db.Employees.Where(x => x.Id == EmpID)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Employees)
.Distinct()
.SelectMany(x => x.PurchaseOrders);
var result = from po in poList2
where po.CompanyId == companyId &&
po.PartyId == partyId &&
!po.IsDeleted
select po into newPO
select new
{
Name = newPO.PONo,
Id = newPO.Id
};
And if you need the result you originally intended to get from poList2:
var result2 = poList2.Select(po =>
{
Name = po.PONo,
Id = po.Id
};
So, generally speaking, you can do more with your query bodies if you postpone the projection to anonymous types.
Side note: I used !po.IsDeleted because I'd strongly recommend to make the field not nullable, with false as default value.
I have the following in an MVC4 app. I want to filter the load by both keys, there could be many to many but both the keys together represent a unique row. The goal to to explicitly load these collections only when needed and filter by both sides of the relationship.
I have the following Entity.DBContext, it works but only for the UserId key.
context.UserProfiles.Include(o => o.CoachOfOrginizations).Where(p => p.UserId == UserId).Single()
Also this loads all of them, but of course doesnt filter at all, just showing you so you know that I set up my fluent code properly.
context.Entry(this).Collection(t => t.AdministratorOfOrginizations).Load();
modelBuilder.Entity<UserProfile>()
.HasMany(p => p.CoachOfOrginizations)
.WithMany(t => t.Coaches)
.Map(mc =>
{
mc.ToTable("OrganizationCoaches");
mc.MapLeftKey("UserProfileID");
mc.MapRightKey("OrganizationID");
});
CoachOfOrginizations is the following property on UserProfile.
public ICollection<Organization> CoachOfOrginizations { get; set; }
What i would like is to filter my original .Include above based on Organization.ID (the other key) and the currently used key p.UserId. I've tried the following and it doesn't work, any advice? "this" is the UserProfile object.
context.Entry(this)
.Collection(b => b.CoachOfOrginizations)
.Query()
.Where(p => p.ID == orgID)
.Load();
You can do both filtering in a single query. See conditional includes.
var query = context.UserProfiles
.Where(p => p.UserId == UserId)
.Select(p => new { p, Orgs = p.CoachOfOrginizations.Where(o => o.ID == orgID) });
var profiles = query.AsEnumerable().Select(a => a.p);
Within my Context file, I set up a many to many relationship between my Location class and Program class.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Location>()
.HasMany(u => u.Programs)
.WithMany(r => r.Locations)
.Map(m =>
{
m.ToTable("LocationsPrograms");
m.MapLeftKey("LocationId");
m.MapRightKey("ProgramId");
});
}
I'm creating a search/filter form where the user will need to be able to filter the locations by selecting a program.
My thought was to query the junction (M2M) table and then join that back up with the locations table.
The problem is that I don't have a class representing the M2M table other than in my OnModelCreating method.
Can I get an example on how to do this?
Basically select * from locations l join locationsprograms lp on l.LocationId = lp.locationid and lp.programid = whatever was passed in.
Thank you.
var locations = dbContext.Locations
.Where(l => l.Programs.Any(p => p.ProgramId == whateverWasPassedInId))
.ToList();
Or (works because your are filtering by the primary key property of Program):
var locations = dbContext.Programs
.Where(p => p.ProgramId == whateverWasPassedInId)
.Select(p => p.Locations)
.SingleOrDefault();