I used ADO.NET Entity Database Model (auto-generated) for my angularJS application using database model shown below:
Currently I am using this code to get all data from Contact table:
ContactsEntities db = new ContactsEntities();
public JsonResult GetAll()
{
return Json(db.Contacts.ToList(), JsonRequestBehavior.AllowGet);
}
What I want to achieve is to get all data from database. Is there way to get all data in single "query" or do I need to call
return Json(db.{MODEL NAME}.ToList(), JsonRequestBehavior.AllowGet);
for each model(table) to get data? Is there better solution to get all data from database or do I need to call each model separately?
You should try something like this:
var data = (from c in db.Contacts
from e in db.Emails.Where(x => x.id == c.id_email).DefaultIfEmpty()
from p in db.Phones.Where(x => x.id == c.id_phone).DefaultIfEmpty()
from t in db.Tags.Where(x => x.id == c.id_tag).DefaultIfEmpty()
select new
{
id = c.id,
phone = p.number,
email = e.email1,
tag = t.tag1,
firstname = c.firstname,
lastname = c.lastname,
address = c.address,
city = c.city,
bookmarked = c.bookmarked,
notes = c.notes
}).ToList();
return Json(data, JsonRequestBehavior.AllowGet);
Or if you want to prepare yourself for the future, when you add multiple properties to the Contact/Email/... classes and don't want to change your code:
var data = (from c in db.Contacts
from e in db.Emails.Where(x => x.id == c.id_email).DefaultIfEmpty()
from p in db.Phones.Where(x => x.id == c.id_phone).DefaultIfEmpty()
from t in db.Tags.Where(x => x.id == c.id_tag).DefaultIfEmpty()
select new
{
Contact = c,
Email = e,
Phone = p,
Tag = t
}).ToList();
Related
I have figured out that to get the staff members from a company I use the following:
public ActionResult Index()
{
int staffID = (int)Session["StaffID"];
var staffRecord = db.Staffs.FirstOrDefault(staff => staff.StaffID == staffID);
var company = staffRecord.Company;
var staffForCompany = company.Staffs;
return View(staffForCompany);
}
and this gets the bookings for that staff/company:
public ActionResult Index()
{
int staffID = (int)Session["StaffID"];
var staffRecord = db.Staffs.FirstOrDefault(staff => staff.StaffID == staffID);
var company = staffRecord.Company;
var bookingsForCompany = company.Bookings;
return View(bookingsForCompany);
}
What I am wanting to know is how do I get data from a table that is not directly associated with the staff/company tables.
I am wanting the Customers that relate to the company of the staff member logged in.
See image here http://www.adamoxenhamsmith.co.uk/Uploads/download.jpg
From the ER diagram given in the image, it seems Company has 1..n bookings and each booking is tied to 1 Customer
This should work:
var customers = staffRecord.Company.Bookings.Select(b => b.Customer);
This should work:
var customers = db.Staffs
.Where(s => s.StaffID == staffId)
.Select(s => s.Company)
.SelectMany(c => c.Bookings)
.Select(bk => bk.Customer)
.ToList();
I have a table as
StudentName / Classroom / GradeA / GradeB / GradeC / GradeDate
The students classrooms are fixed so that column never changes.
Each student has multiple GradeA, GradeB and GradeC values with different GradeDate.
public virtual IList<ClassroomDetail> GetLatestClassroomDetail(string classroom)
{
var query = from pc in _classroomDetailRepository.Table
where pc.Classroom == classroom
select pc;
var result = new List<ClassroomDetail>(query);
return result;
}
Above query returns everything and there are multiple same students in the list.
How can I only get latest values?
Tables:
ClassroomMaster
Id
UpdateDate
Classroom
ClassroomDetail
Id
Cm_Id (has foreign key with ClassroomMaster Id)
StudentName
GradeA
GradeB
GradeC
GradeDate
On Controller
var bdetail = _classroomService.GetLatestClassroomDetail(classroom).OrderBy(d => d.StudentName);
var model = new List<ClassroomDetail>();
foreach (var pr in bdetail)
{
model.Add(new ClassroomDetail
{
Id = pr.Id,
Classroom = pr.Classroom,
StudentName = pr.StudentName,
GradeA = pr.GradeA,
GradeB = pr.GradeB,
GradeC = pr.GradeC,
GradeDate = pr.GradeDate,
});
}
return PartialView(model);
It will solve your problem
var query = _classroomDetailRepository.Table
.Where(a => a.Classroom == classroom)
.Select(b => b.OrderByDescending(y => y.GradeDate).Take(1).FirstOrDefault());
I finally found the solution :D
public virtual IList<ClassroomDetail> GetLatestClassroomDetail(string classroom)
{
var query = _classroomDetailRepository.Table
.Where(z => z.Classroom == classroom)
.GroupBy(x => x.StudentName)
.Select(x => x.OrderByDescending(y => y.GradeDate).Take(1).FirstOrDefault());
var result = new List<BunkerPriceDetail>(query);
return result;
}
Please look at my code below
var result = (from c in db.vCompanies
where id == c.id
from user in db.Users
select new ViewCompanyModel()
{
Id = c.id,
Descripton = c.Descripton,
Name = c.Name,
ImageLink = c.ImageLink,
AdminEmail = c.Email,
Users = db.eUsers
.Where(o => o.CompanyName.Equals(c.Name))
.Select(o => new UserManageViewModel.UserViewModel
{
Id = o.UserId,
Name = o.LastName,
Email = o.Email,
Company = o.CompanyName,
ListOfRoles = user.AspNetUsers.AspNetRoles.Select(x=>x.Name).ToList()
})
}).FirstOrDefault();
I receive not correct data in ListOfRoles - I receive data only of first user.
I tried to add something like this
Where(x=>x.UserId == o.UserId)
I also tried change for this
ListOfRoles = db.Users.Where(x=>x.UserId == o.UserId).Select(x=>x.AspNetUsers.AspNetRoles)
But in this case I can't select x.Name.
I am doing something wrong.
Please advise me.
if(result != null)
{
foreach (var user in result.Users)
{
var roles = db.Users.Where(x => x.UserId == user.Id).Select(x => x.AspNetUsers.AspNetRoles).FirstOrDefault();
user.ListOfRoles = roles.Select(x => x.Name).ToList();
}
}
This is the answer! It's work!
I have the following database code:
static IEnumerable<dynamic> GetData(bool withchildren) {
using (var model = new testEntities()) {
var res = default(IQueryable<dynamic>);
if (withchildren) {
res = model.UserSet
.Where(u => u.name != "")
.Select(u => new {
Name = u.name,
Email = u.email,
Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
})
});
} else {
res = model.UserSet
.Where(u => u.name != "")
.Select(u => new {
Name = u.name,
Email = u.email
});
}
return res.ToList()
}
}
I would like to shrink the code and write it like this:
static IEnumerable<dynamic> GetData(bool withchildren) {
using (var model = new testEntities()) {
var res = default(IQueryable<dynamic>);
res = model.UserSet
.Where(u => u.name != "")
.Select(u => {
dynamic item = new {
Name = u.name,
Email = u.email
};
if(withchildren) {
item.Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
});
}
return item;
});
return res.ToList();
}
}
But Visual Studio complains, that it cannot convert the lambda expression into an expression tree.
My question is, is there a way to accomplish that with the Entity Framework and Linq? I really wouldn't want to use ADO.net directly.
Maybe there is even a better version to shrink it, than the code that I imagine.
Here is a related question with Linq-To-Objects.
EDIT
Before someone asks, I use dynamic in the example code to make it a bit easier and faster.
EDIT 2
My goal with this approach is, to only query the fields I need to improve performance. Check http://www.progware.org/Blog/post/Slow-Performance-Is-it-the-Entity-Framework-or-you.aspx.
At the moment we use something like
static IEnumerable<dynamic> GetData(bool withchildren) {
using (var model = new testEntities()) {
var res = default(IQueryable<dynamic>);
res = model.UserSet
.Where(u => u.name != "")
.ToList();
return res;
}
}
And the performance is, according to Glimpse, horrible.
EDIT 3
Short side note, I made up some quick and dirty code. That is, why the foreach at the end was not needed. The actual code is not available at the moment.
Is there any reason you couldn't use:
res = model.UserSet
.Where(u => u.name != "")
.Select(u => new {
Name = u.name,
Email = u.email,
Groups = withchildren
? u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
})
: null;
})
};
or perhaps:
res = model.UserSet
.Where(u => u.name != "")
.ToList() // ToList() here to enumerate the items
.Select(u => {
dynamic item = new {
Name = u.name,
Email = u.email
};
if(withchildren) {
item.Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
});
}
return item;
});
One approach that would allow you to eliminate some code would be:
var res = model.UserSet.Where(u => u.name != "");
if (withchildren) {
res = res.Select(u => new {
Name = u.name,
Email = u.email,
Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
})
});
} else {
res = res.Select(u => new {
Name = u.name,
Email = u.email
});
}
One of the most requested by community feature is support of multi-line expressions in EF,
however so far, you can use only conditional operator "?:" as well as wrap result in
one common type, so both your results will have to have "Groups" field.
Also there are an extensions to linq-providers such as https://www.nuget.org/packages/LinqKit/ ,
however they are based on own conventions so any developer should study it in depth before
taking advance in applying and supporting code written upon that extensions.
I have the following as part of my entity framework class:-
public CustomerDetails GetCustomer(int id) {
var customerDetails = entities.AccountDefinitions
.Where(a => a.ORG_ID == id)
.Select(cd => new CustomerDetails
{
AD = cd,
SD = cd.SDOrganization,
AA = cd.SDOrganization.AaaPostalAddresses,
SN = cd.SiteDefinitions,
Ar = cd.SiteDefinitions.SelectMany(a => a.DepartmentDefinitions.SelectMany(a2 => a2.SDUsers.Select(a3 => a3.AaaUser)))
})
.SingleOrDefault();
return customerDetails;
}
Inside the inner .Select I have five assignments operations, but since some assignments depend upon the other so how I can write something such as:-
Ar = SN.SelectMany(…….)
So in this way I will only query the database only one time to retrieve the cd.SiteDefenitions??
One option would be to do it like this:
var customerDetails = entities.AccountDefinitions
.Where(a => a.ORG_ID == id)
.Select(cd => new CustomerDetails
{
AD = cd,
SD = cd.SDOrganization,
AA = cd.SDOrganization.AaaPostalAddresses,
SN = cd.SiteDefinitions
})
.SingleOrDefault();
if (customerDetails != null)
{
customerDetails.Ar = customerDetails.SN...
}
return customerDetails;
I know it may not be quite what you were looking for, but you're not going to be able to get at the SN property during the parameterless constructor operation like that (AFAIK).