Replace view SQL Server with public List<> in c#.net - c#

I am building a c#.net web application which draws data from a SQL Server. I have a view in SQL Server based on a single table containing multiple records for the employees. At most one record can be active, but it is not necessarily the one with MAX(ID). It contains the history as well as the current status of the employees. This is some legacy I have to work with.
In order to get the correct record I group by the employee code, and total the boolean field InDienst ('currently employed'), which can be 1 at most. Based on this selection I can go back and select the correct record applying MAX(ID).
SELECT
Personeelscode_ref AS Personeelscode,
SUM(InDienst) AS InDienst
FROM dbo.tPersoneel
GROUP BY Personeelscode_ref
This works fine.
However, as I am not the only one with access to the database, I would like to move this to the c#.net controller (or a model) and apply a List<> statement in c# which replaces the view. Something like this:
public static List<tPersoneel> listEmployeeAll = EmployeeDB.tPersoneel
.GroupBy(x => x.Personeelscode_ref)
.Select( new tPersoneel
{
Personeelscode_ref as Personeelscode,
(InDienst).sum()
})
.ToList();
Can you show me what the correct c#.net code would be?
Thanks much in advance!

use this code
List<tPersoneel> listEmployeeAll = EmployeeDB.tPersoneel.GroupBy(x => x.Personeelscode_ref)
.Select(y => new {
Personeelscode = y.Key.Personeelscode_ref,
InDienst = y.Sum(x => x.InDienst)
}).ToList();
or
List<tPersoneel> listEmployeeAll = (from c in EmployeeDB.tPersoneel
group c by c.Personeelscode_ref into g
select new
{
Personeelscode = y.Key.Personeelscode_ref,
InDienst = y.Sum(x => x.InDienst)
}).ToList();

Related

Entity Framework Takes Too Much Time where Adding "WHERE Clause"

I'm working on Schools System, and the System have many Users(teachers And Managers).
(Tools)
Asp.net 5 (MVC With C#) VS 2015
SQL SERVER (Azure)
Code-First Approach
Each user Assigned to One Or More Of Classes.
(The User Should only See His Classes And Students inside of Classes)
in the other side
to catch Each User Classes
I've write this Method
public static IEnumerable<Class> GetClasses()
{
string UserId = HttpContext.Current.User.Identity.GetUserId();
ApplicationDbContext db = new ApplicationDbContext();
var Job = db.Jobs.Where(j => j.UserId == UserId).FirstOrDefault();
if (Job.EntityLevelID == 1)
{
var x = db.Classes.Where(a => a.Levels.SupervisionCenter.Organization.Id == Job.EntityID) as IEnumerable<Class>;
return x;
}
return null;
}
in The Students List Controller I just want the User to get his Students which are Only in his Classes
to get all the Students i write this Code
var items = db.Students.AsEnumerable().Where(o => o.Name.ToLower().Contains(search)).AsQueryable();
This Code will Give all the Students, it takes around 10 Sec to load and finish all the data (But that's is not needed Bcs, i need to Filter on ClassID Field).
when i need to filter on user Permissions based-classes
I've edit the code to be
var items = db.Students.AsEnumerable().Where(o => o.Name.ToLower().Contains(search))
.Where(s => UserDB.GetClasses().Select(c => c.Id).Contains(s.ClassID.Value))
.AsQueryable();
in the Previous case, when i add the where query it takes more than 80 Sec
EDIT (1)
The Organization Chart Will Be
Organizations
SuperVisionCenter
Schools
Classes
So I don't know what is the Problem I've made it here, can you please advise me for this
Thanks And Regards.
The very first thing that is slowing you down is AsEnumerable()
See here the effects of using AsEnumerable()
Basically you are getting all students in memory then running your where clause in app memory instead of just getting selected students.
Edit 1:
o.Name.ToLower().Contains(search)
I dont think you need to do ToLower() as MSSQL is case insensitive by default. This should remove the need for db.Students.AsEnumerable()
Edit 2:
Why don't you use join ? That would be a good optimisation to begin with.
something like
List<Student> data = (from student in db.Students
join clss in db.Classes on student.Class equals clss
where student.Name.Contains(search)).ToList()
This solved My Problem, and it takes around 3 to 4 seconds only.
int[] Classes = UserDB.GetClasses().Select(c => c.Id).ToArray();
var items = db.Students.Where(o => o.Name.ToLower().Contains(search))
.Where(r => Classes.Contains(r.ClassID.Value)).AsQueryable();

use items in select query that don't include in Group by

I am using EF6 to develop an application that uses a huge data,so in one of my query
his = db.HISTORies.ToList();
front = db.Fronts.ToList();
warehouses = db.Warehouses.ToList();
//------
var q =
his.GroupBy(j => new { j.Line_Number_PGZ, j.MAT_0_PG,j.JOINT_NO_PGZ }).ToList().Select(m => new gridView()
{
JointNumber = m.Key.JOINT_NO_PGZ,
material0 = m.Key.MAT_0_PGZ,material0Name =his.Where(i=>i.MAT_0_PGZ==m.Key.MAT_0_PGZ).First().Code_0_Object_PGZ,
line = m.Key.Line_Number_PGZ
}).OrderByDescending(i => i.material0Need).ToList();
As you can see i fetch all my database to my application .so in my query i grouped my data based on 2 columns ,but my problem is the his has a lot of records so in this line
his.Where(i=>i.MAT_0_PGZ==m.Key.MAT_0_PGZ).First().Code_0_Object_PGZ
I again search an items in this table and this line makes my application to be so slow how can fix this query?
The Code_0_Object_PGZ is in his list but it can be accessed in the select statement !!!
I want to know how can i access Code_0_Object_PGZ without include it in groupby ?
best regards

Linq lambda expression many to many table select

I have three tables, which two of them are in many to many relationship.
Picture:
This is the data in middle mm table:
Edit:
Got until here, I get proper 4 rows back, but they are all the same result(I know I need 4 rows back, but there are different results)
return this._mediaBugEntityDB.LotteryOffers
.Find(lotteryOfferId).LotteryDrawDates
.Join(this._mediaBugEntityDB.Lotteries, ldd => ldd.LotteryId, lot => lot.Id, (ldd, lot) =>
new Lottery
{
Name = lot.Name,
CreatedBy = lot.CreatedBy,
ModifiedOn = lot.ModifiedOn
}).AsQueryable();
My question is, how can I retrieve all the Lotteries via many to many table WHERE I have LotteryOfferId given only?
What I want to achieve is to get data from lottery table by LotteryDrawDateId.
First I use LotteryOfferId to get DrawDates from middle table, and by middle table I get drawDateIds to use them in LotteryDrawDate table. From that table I need to retreive Lottey table by LotteryId in LotteryDrawDate table.
I gain this by normal SQL(LotteryOffersLotteryDrawDates is middle table in DB, not seen in model):
select
Name, Lotteries.CreatedBy, Lotteries.ModifiedOn, count(Lotteries.Id)
as TotalDrawDates from Lotteries join LotteryDrawDates on Lotteries.Id
= LotteryDrawDates.LotteryId join LotteryOffersLotteryDrawDates on LotteryDrawDates.Id =
LotteryOffersLotteryDrawDates.LotteryDrawDate_Id
where LotteryOffersLotteryDrawDates.LotteryOffer_Id = 19 group by
Name, Lotteries.CreatedBy, Lotteries.ModifiedOn
But Linq is different story :P
I would like to do this with lambda expressions.
Thanks
db.LotteryOffer.Where(lo => lo.Id == <lotteryOfferId>)
.SelectMany(lo => lo.LotteryDrawDates)
.Select( ldd => ldd.Lottery )
.GroupBy( l => new { l.Name, l.CreatedBy, l.ModifiedOn } )
.Select( g => new
{
g.Key.Name,
g.Key.CreatedBy,
g.Key.ModifiedOn,
TotalDrawDates = g.Count()
} );
You can do this:
var query = from lo in this._mediaBugEntityDB.LotteryOffers
where lo.lotteryOfferId == lotteryOfferId
from ld in lo.LotteryDrawDates
group ld by ld.Lottery into grp
select grp.Key;
I do this in query syntax, because (in my opinion) it is easier to see what happens. The main point is the grouping by Lottery, because you get a number of LotteryDrawDates any of which can have the same Lottery.
If you want to display the counts of LotteryDrawDates per Lottery it's better to take a different approach:
from lot in this._mediaBugEntityDB.Lotteries.Include(x => x.LotteryDrawDates)
where lot.LotteryDrawDates
.Any(ld => ld.LotteryDrawDates
.Any(lo => lo.lotteryOfferId == lotteryOfferId))
select lot
Now you get Lottery objects with their LotteryDrawDates collections loaded, so afterwards you can access lottery.LotteryDrawDates.Count() without lazy loading exceptions.

Getting Entity Framework to eager load on Group By

I know that changing the shape of a query causes Entity Framework to ignore the include calls but is there a way I can get it to load the sub properties when I do a select many and a group by. In the following example I want to notify all the employees who have a job booked in a certain time period. Calling .ToArray() after the where only hits the database once but I am doing the SelectMany and GroupBy in memory. Is there a way I can get the SelectMany and the GroupBy to happen on the SQL server and still include the ServiceType and Ship and the Employee details?
I am looking for a way to make one SQL call to the database and end up with a list of Employees who have a job in the time period and the jobs they are assigned to.
var employeeJobs = DataContext.Jobs.
Include("ServiceType").
Include("Ship").
Include("JobEmployees.Employee").
Where(j => j.Start >= now && j.Start <= finish).
OrderBy(j => j.Start).
ToArray().
SelectMany(j => j.JobEmployees, (j, je) => new {
Job = j,
Employee = je.Employee
}).GroupBy(j => j.Employee);
The following should work:
var q = from e in DataContext.Employees
where e.Job.Start > ....
order by e.Job.Start
select new {Employee = e, Job = e.Job, Ship = e.Job.Ship, ServiceType = e.Job.ServiceType}; // No db hit yet.
var l = q.GroupBy(item=>item.Employee) // no db hit yet.
.ToList(); // This one causes a db hit.
why don't you create a view and then reference this from the EF?
, this also has the added benefit of the database server doing the work, rather than the app server.
Trying move the Include()'s to the very end after your groupby.

Retrieving all values as strings from SQL Server

I'm currently using EF Code-First, and I'd like to SELECT data from many tables in the database. This query is a customizable query, and hence I can't predict what kind of data I will be retrieving.
At first, when I tried running ctx.Database.SqlQuery<string>(sql, param), I ran into an exception when facing a DateTime value. I'd like to do this without casting it on the server side.
Does anybody have any idea how I can go about doing it? It can be in LINQ, LINQ-SQL, or purely SQL--so long as it gets the job done! Thanks guys...
You will not get it. Linq-to-entities will not make transformation to list of strings. Your best chance is executing normal queries and do conversion and transformation your application.
Argument that you don't know which columns user selects just means you need more dynamic solution - Linq-to-entities is not a good tool for you (except if you try to use Dynamic Linq or build expression trees manually). Use ESQL or SQL directly.
When selecting data from many tables, use anonymous types to encapsulate the properties(fields) you want to select from these tables into a new entity, something like:
var query = _db.Categories.Join(
_db.Products,
c => c.CategoryId,
p => p.CategoryId,
(category, product) =>
new
{
ProductName = product.Name,
CategoryName = category.Name,
ExpiryDate = product.ExpiryDate
});
You can achieve string values by casting your data fields to string in this way:
var query = _db.Categories.Join(
_db.Products,
c => c.CategoryId,
p => p.CategoryId,
(category, product) =>
new
{
ProductName = product.Name.toString(),
CategoryName = category.Name.toString(),
ExpiryDate = product.ExpiryDate.toString()
});

Categories

Resources