I want In operator in mvc Linq.
like this sql (stud_ID is int, primary key and auto increment):
select * from student where stud_ID in (1,4,6,10,5);
how can I adapt for linq this sql?
like
List<int> nl = new List<int>();
nl.add(1);
nl.add(4);
nl.add(6);
nl.add(10);
nl.add(5);
List<student> students = db.student.where(a => a.stud_ID.In(nl)).toList();
//this code is fitting from my mind :D
or the other scenario
List<student> st = db.studentOrderBy(x => Guid.NewGuid()).Take(5); //only for create auto list student type
List<student> students = db.student.where(
a => a.stud_ID.In(st.Select(b => b.stud_ID).toList())
).toList(); //again fitting
I can this
List<student> students = new List<student>();
foreach(var item in nl)
{
students.add(db.student.where(a => a.stud_ID == item).First());
}
but I dont want to use for or foreach or do-while or while :D
try this:
List<student> students = db.student.where(a => nl.Contains(a.Stud_ID)).toList();
This checks, if the student ID is present in the List nl. If so, the student gets returned in the result.
Your second requirement is different, if I understand it correctly. You have two collections of studentes, and want to know which students are also in st.
var intersectedList = students.Intersect(st);
Try this
List<student> students = db.student.Where<student>(a => nl.Contains(a.stud_ID)).ToList<student>();
Related
In my database, I have a table called Employee and it has columns EmpNames and EmpId which same EmpId created User table with user levels. I want to get a list of empNames and id's to who are user level equal to the 4.
This is how I got empname list for a drop down list
List<M_Employee> EmpList = db.CreateEmployee.Where(x => x.Status == true).ToList();
List<SelectListItem> EmpDropDown = EmpList.Select(x => new SelectListItem { Text = x.EmpName, Value = x.Id.ToString() }).ToList();
Same way I have tried to query the user level = 4 and tried to join emp table with user table to get the emp names who assigned user levels to 4 but it didn't work.
Here is my code for that
List<int> TopEmp = db.Master_Users.ToList().Where(r => r.EmpId == int.Parse(db.CreateEmployee.Where(x=> x.Id))).ToList().
Can you help me on this?
Firstly, you need to understand how ToList works.
When you call ToList it means that Entity framework will execute the sql statement constructed at that point and retrieve the results into memory.
You generally want to construct your entire query first and then have that query get all the data you want from the database in the format of an object you want by using .Select(x => x.whatever).ToList(). Otherwise you'll be making multiple calls to the database to get bits of data here and there and then joining them or working with them unnecessarily in memory which is slower than having the database do it.
So your first query where you get the select list items can be rewritten like this:
List<SelectListItem> EmpDropDown = db.CreateEmployee
.Where(x => x.Status == true)
.Select(x => new SelectListItem { Text = x.EmpName, Value = x.Id.ToString() })
.ToList()
And from what you've described you should be able to rewrite the 2nd query like this:
List<int> TopEmp = (from u in db.Master_Users
join e in db.CreateEmployee on u.EmpId equals e.Id
where u.Level == 4
select e.Id
).ToList();
This is using a different query syntax but allows to specify the key to join on easily as I don't know how your foreign keys and navigation properties are setup.
I can't see you dbcontext, maybe it is possible to use include too, but for the start try this
List<SelectListItem> EmpDroDown = (from emp in db.CreateEmployee
join usr in db.Master_Users on emp.Id equals usr.EmpId
where emp.Status == true && usr.UserLevel==4
select new SelectListItem { Text = em.EmpName,
Value = emp.Id.ToString() }).ToList();
So I was working on a DropDown list and it works, but it has many duplicate emails, I just want to see distinct emails... So I tried doing .Distinct() in the model class, but that still gave me duplicates..
Model Class:
public string One_Manager_Email{ get; set; }
public List<Hello> getManagers()
{
var que = (from wr in db.View
select new Hello
{
O_Manager_Email= wr.One_Manager_Email
}).Distinct().ToList();
return que;
}
Controller Class: (This is probably where the problem is happening)
public ActionResult Index()
{
test = new Hello();
ViewBag.Managers = new SelectList(test.getManagers(), "", "O_Manager_Email");
return View(test.getStuff());
}
View Class:
<div>
#Html.DropDownList("Managers", ViewBag.Managers as SelectList)
</div>
Any help would be great, thank you!
You need to group your objects by the property you want them to be distinct by, and then select the first element of the grouping.
public List<Hello> getManagers()
{
var que = (from wr in db.View
select new Hello
{
O_Manager_Email= wr.One_Manager_Email
})
.GroupBy(g => g.O_Manager_Email) //group by property
.Select(g => g.First()) //take first element from every grouping
.ToList();
return que;
}
For some more details, you can see this post that has more details on grouping and distinct: LINQ's Distinct() on a particular property
Distinct won't work on objects like that, as objects are always distinct, but you can try using group by in your query, something along these lines:
var que = (from wr in db.View
group new {wr.One_Manager_Email}
by new {wr.One_Manager_Email} into grouped
select new Hello
{
O_Manager_Email= grouped.Key.One_Manager_Email
}).ToList();
return que;
If you just need email address, you can select just string instead of selecting Hello object. If you select Hello object and try to distinct you like that way, you obviously get duplicated items. Because every object is already unique.
I believe you have already answer. GroupBy might solve your problem. However unless you really need GroupBy, don't use GroupBy! It's really expensive operation.
In your case, you should use DistinctBy.
var distinctList = list.DistinctBy(x => x.Prop).ToList();
On your code:
var que = (from wr in db.View
select new Hello
{
O_Manager_Email = wr.One_Manager_Email
}).DistinctBy(x=>x.O_Manager_Email).ToList();
Oh, in terms of DistinctBy usage, you should import namespace of Microsoft.Ajax.Utilities.
using Microsoft.Ajax.Utilities;
I have a method of type IQueryable<T> and here is it's implementation:
public IQueryable<T> Get()
{
return db.Set<T>();
}
I must write LINQ query where I want to join two tables (left join). It is Identtiy table Users and my custom table PersonalInformation which extend User registration fields and now I want to call this method in my LINQ query and it is good. Here is my Linq:
IRepository<PersonalInformation> personRepository;
IRepository<ApplicationUser> usersRepository;
var query = personRepository.Get();
var test = usersRepository.Get()
.GroupJoin(query,
n => n.Id,
m => m.UserId,
(n, ms) => new { n, ms = ms.DefaultIfEmpty() })
.SelectMany(z => z.ms.Select(m => new PersonalInfoModel
{
Name = m.Name,
LastName = m.LastName,
Email = z.n.Email
}));
But I have an error in
var test = usersRepository.Get() - System.NotSupportedException. So method Get from personRepository called good but usersRepository method return null. Where I did the mistake?? Thanks
It looks likely that you are having an error combining queries from two different database contexts. Your custom PersonalInformation is probably in a custom DBContext while Users is in the IdentityDBContext. See this related question. You can either:
Move all of your tables into the same context.
Avoids future confusion between these tables
More efficient if you end up with lots of associations across contexts.
A more involved solution just to get this one example working.
Query your tables separately and combine in memory.
Less scalable if you have a huge number of users.
These operators will cause EF to return the results so you can process in memory.
var people = personRepository.Get().ToList();
var users = usersRepository.Get().ToList();
var infoModels = users.GroupJoin(people,
u => u.Id,
p => p.UserId,
(u, mp) => new { n, ms = ms.DefaultIfEmpty() })
.SelectMany(z => z.ms.Select(m => new PersonalInfoModel
{
Name = m.Name,
LastName = m.LastName,
Email = z.n.Email
}));
I am trying to write a query that includes 2 joins.
1 StoryTemplate can have multiple Stories
1 Story can have multiple StoryDrafts
I am starting the query on the StoryDrafts object because that is where it's linked to the UserId.
I don't have a reference from the StoryDrafts object directly to the StoryTemplates object. How would I build this query properly?
public JsonResult Index(int userId)
{
return Json(
db.StoryDrafts
.Include("Story")
.Include("StoryTemplate")
.Where(d => d.UserId == userId)
,JsonRequestBehavior.AllowGet);
}
Thank you for any help.
Try to flatten your hierarchy if it works for you. Here is a sample, and you may want to customize it for your needs.
var result = from c in db.Customers
join o in db.Orders
on c equals o.Customers
select new
{
custid = c.CustomerID,
cname = c.CompanyName,
address = c.Address,
orderid = o.OrderID,
freight = o.Freight,
orderdate = o.OrderDate
};
If flattering does not meet your requirements then you need to use query that returns a Nested Group. Finally, look at the following link for more references - LINQ Query Expressions .
Assuming a Entity Framework, in a LazyLoading context.
We have 3 entities:
Product(which has many Order Details)
OrderDetails(which has many Details)
Detail
The following query brings all Products with Name=Books. And to each of these products loads all the OrderDetails which OrderDetail.Quantity>5.
var query = anEntityManager.Products.Where(p => p.Name == "Books")
.Select(p => new { Product = p, OrderDetails = p.OrderDetails.Where(od => od.Quantity > 5) });
var results = query.ToList();
var products = results.Select( x => x.Product);
My Problem is that the Details of each OrderDetail are NOT being retrieved from DB. How can I make an Include in this query so Details are also loaded from DB in the same query?
I think you need to extend your projection:
var query = anEntityManager.Products.Where(p => p.Name == "Books")
.Select(p => new
{
Product = p,
OrderDetails = p.OrderDetails.Where(od => od.Quantity > 5),
Details = p.OrderDetails.Where(od => od.Quantity > 5)
.SelectMany(od => od.Details)
});
var results = query.ToList();
var products = results.Select( x => x.Product);
Using Include in a projection is not supported, so this (a bit ugly) code is the only way I know of to get the result in one database query.
You can probably also use Select instead of SelectMany (Details would then be an IEnumerable<IEnumerable<Detail>> instead of a flat IEnumerable<Detail>) because you are throwing away the projected properties anyway - except the Product property.