EF 6 query get a single entry from other table - entity-framework-6

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)
}

Related

how to handle null value in many to many relationship

I am trying to achieve something like this:
if there is a matching id then filter result according to it otherwise bypass the condition
.Where(x => x.NeighbourhoodId == (id ?? x.NeighbourhoodId)
but i am not getting correct syntax with many to many relationship:
public JsonResult GetPost(int? id, int? tagid)
{
var ret = from data in db.Posts.Include(x => x.Tags)
.Include(x => x.Neighbourhood)
.OrderByDescending(x => x.PostedDate)
.Where(x => x.NeighbourhoodId == (id ?? x.NeighbourhoodId)
&& x.Tags.Any(t => t.TagId == tagid))
.ToList()
select new
{
TagName = string.Join(",", data.Tags.Select(t => t.TagName)),
Message = data.Message,
// and other related stuff
}
here, as u can see,this where clause contains multiple conditions i want to filter post.There will be only one parameter with value. means if id parameter have value then tagid will be null and if tagid is null then id would have some value.
now, i want if there is null value in tagid then still this query should run. right now, its not working becoz in database, there is no post with empty tagid or null .how to do it. any suggestions??
If I understand correctly, you need to build the filter dynamically based on the passed parameters like this
var posts = db.Posts
.Include(x => x.Tags)
.Include(x => x.Neighbourhood)
.OrderByDescending(x => x.PostedDate);
if (id != null)
posts = posts.Where(x => x.NeighbourhoodId == id.Value);
if (tagid != null)
posts = posts.Where(x => x.Tags.Any(t => t.TagId == tagid.Value));
var ret = from data in posts
// ... the rest

how to apply inner join in entityframework LINQ method syntax?

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.

How do I get this ViewModel correct?

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>.

Whether I should write, simple join for common records?

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.

MVC 4 explicitly load a many to many EF lookup and filter by both keys

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);

Resources