How to access a list in another method - c#

I am new to .NET and I would like to be able to solve this small problem that I am facing. I want to access a list that is in Info method to be able to use it in InfoCurricular method. I do not know how I can do it, if I create a method if doing everything in one is the best. The methods are separated because they have different attributes which result in different results after the action taken.
Info Method
public async Task<IActionResult> Info(string anoLetivo) {
var nomeuc = new List<NomeUC>();
Main main = new Main();
main.NomeUC = nomeuc;
//user
var user = await GetCurrentUserAsync();
//docente
var IDdocente = _context.Docente.SingleOrDefault(x => x.UserId == user.Id);
var nomeporano = (from nome in _context.NomeUC
join unidadecurric in _context.UnidadeCurricular on nome.NomeUCId equals unidadecurric.NomeUCId
join depart in _context.Departamento on unidadecurric.DepartamentoId equals depart.DepartamentoId
join doc in _context.Docente on depart.DepartamentoId equals doc.DepartamentoId
join nalunos in _context.NAlunos on unidadecurric.UnidadeCurricularId equals nalunos.UnidadeCurricularId
join anoletivo in _context.AnoLetivo on nalunos.AnoLetivoId equals anoletivo.AnoLetivoId
where anoletivo.Ano == anoLetivo && doc.DepartamentoId == IDdocente.DepartamentoId
select new {
nome=nome.Nome
}).ToList();
foreach (var item in nomeporano) {
nomeuc.Add(new NomeUC {
Nome = item.nome
});
}
return View("InfoCurricular", main);
}
InfoCurricular Method
public async Task<IActionResult> InfoCurricular(int ano, int semestre) {
var nomeuc = new List<NomeUC>();
//var docente = new List<Docente>();
var unidadecurr = new List<UnidadeCurricular>();
Main main = new Main();
//main.Docente = docente;
main.UnidadeCurricular = unidadecurr;
main.NomeUC = nomeuc;
//user
var user = await GetCurrentUserAsync();
//docente
var IDdocente = _context.Docente.Where(x => x.UserId == user.Id).ToList();
var uc = (from nome in *nomeporano*
join unidadecurric in _context.UnidadeCurricular on nome.NomeUCId equals unidadecurric.NomeUCId
where unidadecurric.AnoCurricular == ano && unidadecurric.Semestre == semestre
select new {
nome = nome.Nome
}).ToList();
foreach(var item in uc) {
nomeuc.Add(new NomeUC {
Nome = item.nome
});
}
return View(main);
}
In the InfoCurrilar method in the uc variable I want to use in the query the values of the other list that is in the Info method and from these values get a new list after executing the query.
The idea is not to get the list in the two methods but use the nomeporano list as a way of going there to seek values.
But this "nomeporano" have attributes that are different in this two methods. I'm still a little bit confused on how to build the method. In Info method the attribute is one, but in InfoCurricular there are two attributes which is different from the other method. How to build a method to retrieve this "nomeporano" list and use that list in methods Info and InfoCurricular? I can undestrand the ways but i'm stuck on the way to build the method .....

There are 2 ways of doing it:
1.) Add a property in the Model class "Main" for retaining complete value of nomeporano, and since you are passing the model to method InfoCurricular, it can easily be used.
2.) Move the below code in the separate method and call the method in methods Info and InfoCurricular:
Cons: Hitting the database multiple times for same data.
var nomeporano = (from nome in _context.NomeUC
join unidadecurric in _context.UnidadeCurricular on nome.NomeUCId equals unidadecurric.NomeUCId
join depart in _context.Departamento on unidadecurric.DepartamentoId equals depart.DepartamentoId
join doc in _context.Docente on depart.DepartamentoId equals doc.DepartamentoId
join nalunos in _context.NAlunos on unidadecurric.UnidadeCurricularId equals nalunos.UnidadeCurricularId
join anoletivo in _context.AnoLetivo on nalunos.AnoLetivoId equals anoletivo.AnoLetivoId
where anoletivo.Ano == anoLetivo && doc.DepartamentoId == IDdocente.DepartamentoId
select new {
nome=nome.Nome
}).ToList();
Regards,
Rajiv
Happy Coding

Related

C# MVC API URL string value remove case sensitive

I have C# MVC API URL localhost/api/APIValues?Name=Nick. All working but only issue is when I typed Name=nick it won't display result. because my database table name field store Nick. Also my Database table name field has some data example Nick, ANN, tristan, Abbott,BUD. How do I remove string(Name) case sensitive MVC API values?
Example, how do I setup both way work localhost/api/APIValues?Name=Nick and localhost/api/APIValues?Name=nick.
This is my C# code.
public IEnumerable<NameDTO> Get(string Name = "")
{
var nameList = (from o in db.People.AsEnumerable()
where o.name == Name
join s in db.Employee on
o.empID equals s.empID
select new
{
s.empID,
o.Id
}).ToList();
}
My finally out put should work both name "Nick or nick"
localhost/api/APIValues?Name=Nick
localhost/api/APIValues?Name=nick
You can use Equals with StringComparison:
public IEnumerable<NameDTO> Get(string Name = "")
{
var nameList = (from o in db.People.AsEnumerable()
where o.name.Equals(Name, StringComparison.OrdinalIgnoreCase)
join s in db.Employee on
o.empID equals s.empID
select new
{
s.empID,
o.Id
}).ToList();
}
Try this, I think it may help you:
// Use if you want same records with name you provide
public List<NameDTO> Get(string Name = "")
{
var nameList = (from o in db.People.AsEnumerable()
where o.name.Trim().ToLower() == Name.Trim().ToLower()
join s in db.Employee on
o.empID equals s.empID
select new NameDTO()
{
EmpId = s.empID,
Id = o.Id
}).ToList();
}
//use this if you want similar records from database
public IEnumerable<NameDTO> Get(string Name = "")
{
var nameList = (from o in db.People.AsEnumerable()
where o.name.Trim().ToLower().Contains(Name.Trim().ToLower())
join s in db.Employee on
o.empID equals s.empID
select new NameDTO()
{
EmpId = s.empID,
Id = o.Id
}).ToList();
}
}
Made it as simple as it can get. Whenever my query's don't work in a single line it's my preference to break it down into several components. Feel happy to write a one liner though.
var nameList= db.People.AsEnumerable();
People people = new People();
foreach (var x in nameList)
{
var result = x.name.ToLower() == Name.ToLower();
if (result)
{
people = x;
}
}
var Employee = db.Employee.FirstOrDefault(e => e.EmpId == people.EmpId);
NameDTO nameDTO = new NameDTO()
{
EmpId = Employee.EmpId,
Id = People.Id
};
SQL is not case sensitive. And as long as yo're using a library that converts your code to SQL (such as EF) this shouldn't be an issue.
var nameList = (from o in db.People
where o.name == Name
join s in db.Employee on
o.empID equals s.empID
select new
{
s.empID,
o.Id
}).ToList();
The problem is that you're using AsEnumerable() which actually executes the query and then compares the objects in memory instead of comparing in DB. Watch it in the SQL Profiler and you will see the difference.

MVC - Joining multiple table using LINQ / lambda - Using EF

I am implementing a controller and I need to get all staff members which have a certain RiskTypeID, which will be selected by the user when they click on Navigation Item.
Here is how I would create the joins in SQL
SQL
Select
RTHG.RiskTypeID,
SM.FullName
From RiskTypeHasGroup RTHG
Inner join RiskGroup RG On RTHG.RiskGroupID = RG.ID
Inner join RiskGroupHasGroupMembers RGHGM ON RG.ID = RGHGM.RiskGroupID
Inner Join GroupMember GM ON RGHGM.GroupMemberID = GM.ID
Inner Join GroupMemberHasStaffMember GMHSM ON GM.ID = GMHSM.GroupMemberID
Inner Join StaffMember SM ON GMHSM.StaffMemberID = SM.ID
Where RTHG.RiskTypeID = 1
I’ve pulled back data before using Linq and lambda but only using simple expressions, I now need to be able to make a call which will bring back the same data as the sql outlined above, I’ve searched online but can’t find anything similar to my requirement.
Here is my Controller, I placed comments inside as guidance
Controller
public ActionResult ViewRiskTypes(int SelectedRiskTypeID)
{
var RiskTypes = _DBContext.RiskTypes.ToList(); // Get all of the current items held in RiskTypes tables, store them as a List in Var RiskTypes
var ViewModel = new List<RiskTypeWithDetails>(); // Create colletion which holds instances of RiskTypeWithDetails and pass them to the ViewModel
var Details = new RiskTypeWithDetails(); // Create a new instance of RiskType with details and store the instance in var Details
foreach (var RiskType in RiskTypes) // Loop through each Item held in var RiskTypes
{
Details.RiskTypes.Add(new RiskTypesItem { ID = RiskType.ID, Description = RiskType.Description }); // assign each items ID & Description to the same feilds in a new
// instance of RiskTypeItems (which is a property of RiskTypeWithDetails)
}
foreach (var RiskType in RiskTypes) // Loop through each item in RiskTypes
{
if (RiskType.ID == SelectedRiskTypeID) // Check Item ID matches SelectedRiskTypeID value
{
//var Details = new RiskTypeWithDetails();
Details.RiskTypeDescription = RiskType.Description; //assign the Risk type Descripton to RiskTypeWithDetails RiskTypeDescription Property
Details.RiskDetails = _DBContext
.RiskTypeHasGroups
//.GroupMemberTypeHasGroupMembers
.Where(r => r.RiskTypeID == SelectedRiskTypeID) // Where RiskTypeId matches Selected ID bring back following data from Db
.Select(r => new RiskDetails
{
RiskGroupDescription = r.RiskGroup.Description,
GroupMembers = r.RiskGroup.RiskGroupHasGroupMembers
.Select(v => v.GroupMember).ToList(),
//StaffMembers = r.RiskGroup.RiskTypeHasGroups
// .Join(r.RiskGroup.RiskTypeHasGroups,
// a => a.RiskGroupID , b => b.RiskGroup.ID,
// (a, b) => new {a, b})
// .Join(r.RiskGroup.RiskGroupHasGroupMembers,
// c => c.) // Dosent join as I would expect... no idea what to do here
}).ToList();
ViewModel.Add(Details); //Add all data retrieved to the ViewModel (This creates one item in the collection)
}
}
return View(ViewModel);
}
As you will see I want to get all Staff Members with a match for the selected RiskTypeID. I need some assistance in converting the above SQL to work within my controller as a lambda expression
Thanks in advance
You were on the right track with your commented out code! For starters, LINQ has two different sytaxes: query and method chain. You were using the method chain syntax and it can get really unmaintainable really quickly.
For an instance like this, query syntax is where it's at.
Here's the result:
from rhtg in _dbContext.RiskTypeHasGroup
where rhtg.RiskTypeID == 1
join rg in _dbContext.RiskGroup
on rhtg.RiskGroupID equals rg.ID
join rghgm in _dbContext.RiskGroupHasGroupMembers
on rg.ID equals rhtg.ID
join gm in _dbContext.GroupMember
on rg.ID equals gm.ID
join gmhsm in _dbContext.GroupMemberHasStaffMember
on gm.ID equals gmhsm.GroupMemberID
join sm in _dbContext.StaffMember
on gmhsm.StaffMemberID equals sm.ID
select new
{
rhtg.RiskTypeId,
sm.FullName
};
Do note, that I used .Net conventions for the different variables.
Here's some documentation on the query syntax:
https://msdn.microsoft.com/en-us/library/gg509017.aspx
You can write the exact same query in linq as follows:
var query = (from RTHG in _DBContext.RiskTypeHasGroup RTHG
join RG in _DBContext.RiskGroup on RTHG.RiskGroupID equals RG.ID
join RGHGM in _DBContext.RiskGroupHasGroupMembers on RG.ID equals RGHGM.RiskGroupID
join GM in _DBContext.GroupMember on RGHGM.GroupMemberID = GM.ID
join GMHSM in _DBContext.GroupMemberHasStaffMember on GM.ID equals GMHSM.GroupMemberID
join SM in _DBContext.StaffMember on GMHSM.StaffMemberID equals SM.ID
where RTHG.RiskTypeID == 1
select new {RTHG.RiskTypeID,SM.FullName});

returning multiple class model data from linq in list via return method in C#

I have LINQ output which I am trying to pass in list but I am getting following error
in linq result I am trying to pass data from two class model, if I do one class model (listOfCoursesWithoutURL ) then it work but I need to pass processedCourseInstance. I have created ModelView of two classes but not sure what I am missing in this picture
ViewModel
public class CoursesInstanceStudyLevel_ViewModel
{
public CourseInstanceModel _CourseInstanceModel { get; set; }
public StudyLevelModel _StudyLevelModel { get; set; }
}
My Class
public List<CoursesInstanceStudyLevel_ViewModel> ProcessAllCoursesApplicationURL(CourseApplicationsURLFeed_Model _obj)
{
using(var _uof = new Courses_UnitOfWork())
{
_uof.CourseInstances_Repository.GetAll();
var _listOfCoursesWithoutURL = (from b in ListOfCoursesInstances
where b.ApplicationURL == null
select b).ToList();
var processedCourseInstance = (from _courseInstances in _uof.CourseInstances_Repository.GetAll()
join _courses in _uof.Courses_Repository.GetAll() on _courseInstances.CourseID equals _courses.CourseID
join _studylevel in _uof.StudyLevel_Repository.GetAll() on _courses.StudyLevelId equals _studylevel.StudyLevelID
orderby _courseInstances.CourseCode
select new { _courseInstances, _studylevel }).ToList();
return processedCourseInstance; // it doesn't work ... refer to screen shot
// return _listOfCoursesWithoutURL //it works
}
}
Error
here:
select new { _courseInstances, _studylevel })
you are defining an anonymous object. You have a type ready, so use that one:
select new CoursesInstanceStudyLevel_ViewModel
{
_CourseInstanceModel = _courseInstances,
_StudyLevelModel = _studylevel
}
assuming CourseInstanceModel and StudyLevelModel are the correct types
With highlighted line in following code snippet, you are selecting an anonymous object instead of a concrete CourseIntaceStudyLeve_ViewModel
select new { _courseInstances, _studylevel }
You will have to change your query to following..
var processedCourseInstance = (from _courseInstances in _uof.CourseInstances_Repository.GetAll()
join _courses in _uof.Courses_Repository.GetAll() on _courseInstances.CourseID equals _courses.CourseID
join _studylevel in _uof.StudyLevel_Repository.GetAll() on _courses.StudyLevelId equals _studylevel.StudyLevelID
orderby _courseInstances.CourseCode
select new CoursesInstanceStudyLevel_ViewModel(){
_CourseInstanceModel = _courseInstances.FirstOrDefault(),
StudyLevelModel = _studylevel.FirstOrDefault()}).ToList();
I have assumed you would need only first course and first study level based on your view model definition and there for applied FirstOrDefault. You can choose to go along with this or change your view model definition.
here is my answer and it works
var processedCourseInstance =
(from _courseInstances in _uof.CourseInstances_Repository.GetAll()
join _courses in _uof.Courses_Repository.GetAll() on _courseInstances.CourseID equals _courses.CourseID
join _studylevel in _uof.StudyLevel_Repository.GetAll() on _courses.StudyLevelId equals _studylevel.StudyLevelID
orderby _courseInstances.CourseCode
select new CoursesInstanceStudyLevel_ViewModel() {
_CourseInstanceModel = _courseInstances,
_StudyLevelModel = _studylevel
}).ToList();

More efficient way of loading children of entity objects in linq to entity query

I have a rather complex linq to entity query that I'm performing, in the end, I have a result set. I loop through that result set, build business objects and return that list of business objects. it's pretty quick, the problem is that 2 of the child properties are complex objects with their own child objects. for every business object in my loop, I then have to make 2 DB calls to fill its child object. Those 2 calls slow down the overall process, is there a better way to do this? noob to EF here. (EF 4,SQL Server 2008,c#)
Get a result set:
var newresult = from r in result // result is another complex query
join subedit in
(from sa in context.Security_Access
join g in context.Security_UserGroup on sa.EntityID equals g.GroupID
where (sa.PrivledgeID == xx) && g.UserID == userId
select new { user = g.UserID, linkid = sa.LinkID }).Distinct() on new { aid = r.AssetId } equals new { aid = subedit.linkid } into theSubEdit
from subEditAccess in theSubEdit.DefaultIfEmpty()
join subdownload in
(from sa in context.Security_Access
join g in context.Security_UserGroup on sa.EntityID equals g.GroupID
where (sa.PrivledgeID == xx|| sa.PrivledgeID == yy) && g.UserID == userId
select new { user = g.UserID, linkid = sa.LinkID }).Distinct() on new { aid = r.AssetId } equals new { aid = subdownload.linkid } into theSubDownload
from subDownloadAccess in theSubDownload.DefaultIfEmpty()
join subView in
(from sa in context.Security_Access
join g in context.Security_UserGroup on sa.EntityID equals g.GroupID
where (sa.PrivledgeID == xx|| sa.PrivledgeID == yy|| sa.PrivledgeID == 101) && g.UserID == userId
select new { user = g.UserID, linkid = sa.LinkID }).Distinct() on new { aid = r.AssetId } equals new { aid = subView.linkid } into theSubView
from subViewAccess in theSubView.DefaultIfEmpty()
select new { r, EditAccess = (int?)subEditAccess.user, DownloadAccess = (int?)subDownloadAccess.user, ViewAccess = (int?)subViewAccess.user };
I then loop through that result set:
foreach (var asset in newresult)
{
// and build a new business object, set its properties
BoAsset boAsset = new BoAsset();
boAsset.HasEditRights = (asset.EditAccess > 0);
boAsset.HasDownloadRights = (asset.DownloadAccess > 0);
boAsset.HasViewRights = (asset.ViewAccess > 0);
boAsset.Description = asset.r.Description;
boAsset.DetailedDescription = asset.r.DetailedDescription;
boAsset.Keywords = asset.r.Keywords;
boAsset.Notes = asset.r.Notes;
boAsset.Photographer = asset.r.Photographer;
boAsset.PhotographerEmail = asset.r.PhotographerEmail;
boAsset.Notes = asset.r.Notes;
boAsset.Author = asset.r.Author;
// these 2 properties i've commented out are
// complex objects/entities, setting them the way I am
// requires me to call 2 separate methods which make 2 DB trips
// per business object.
//boAsset.Domains = GetAssetDomains(asset.r.AssetId);
//boAsset.DomainEntries = GetAssetCustomDomains(asset.r.AssetId);
myListofObjects.Add(boAsset);
}
return myListofObjects;
Is there a better way?
Just add this .Include("Domains").Include("DomainEntries") to your Linq in in context.Security_Access That should get rows from those tables all in one go.
So your "inner" queries would look like:
from sa in context.Security_Access.Include("Domains").Include("DomainEntries")
join g in context.Security_UserGroup on sa.EntityID equals g.GroupID
where (sa.PrivledgeID == xx) && g.UserID == userId
select new { ...
Here is the documentation from MS: http://msdn.microsoft.com/en-us/library/bb738708.aspx
If you want to improve your performance use compile queries !
You can check the example here.
static readonly Func<AdventureWorksEntities, Decimal,
IQueryable<SalesOrderHeader>> s_compiledQuery2 =
CompiledQuery.Compile<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>>((ctx, total) =>
from order in ctx.SalesOrderHeaders.Include("Orders") where order.TotalDue >= total select order);
MSDN
AND
You can Introduce Include suppose to select all the employees along with their departments . If you have a navigational property, you won't need a join at all. You can use Include like this:
List<Employee> employeesWithDepartments = CreateObjectSet<Employee>().
Include(e => e.Department).
ToList();

Help troubleshooting LINQ query

I have this LINQ query:
var returnList = from TblItemEntity item in itemList
join TblClientEntity client in clientList
on item.ClientNo equals client.ClientNumber
join TblJobEntity job in jobList
on item.JobNo equals job.JobNo
where item.ClientNo == txtSearchBox.Text //Is this filter wrong?
orderby client.CompanyName
select new { FileId = item.FileId, CompanyName = client.CompanyName, LoanStatus = item.LoanStatus, JobNo = job.JobNo, JobFinancialYE = job.JobFinancialYE, VolumeNo = item.VolumeNo };
Why doesn't this return anything?
P/S : All of them are of string datatype.
Have you tried to remove parts of the join to figure out where the problem is and then add those removed parts back again one after one? Start with:
var returnList = from TblItemEntity item in itemList
where item.ClientNo == txtSearchBox.Text //Is this filter wrong?
select new { FileId = item.FileId };
Since you're doing inner joins there could be that one of the joins filters out all the items.
EDIT: When debugging don't expand the return type, the select new {FileId = item.FileId} is all you need to debug.
Still waiting on that sample data.
You say you're getting results filtering by other attributes so why should this be any different? Assuming the user-input txtSearchBox has a reasonable value, try printing the values out onto the debug console and see if you're getting reasonable results. Look at the output window. Try this version of your query:
Func<string,bool> equalsSearch = s =>
{
var res = s == txtSearchBox.Text;
Debug.WriteLine("\"{0}\" == \"{1}\" ({2})", s, txtSearchBox.Text, res);
return res;
};
var returnList = from TblItemEntity item in itemList
join TblClientEntity client in clientList
on item.ClientNo equals client.ClientNumber
join TblJobEntity job in jobList
on item.JobNo equals job.JobNo
//where item.ClientNo == txtSearchBox.Text //Is this filter wrong?
where equalsSearch(item.ClientNo) //use our debug filter
orderby client.CompanyName
select new { FileId = item.FileId, CompanyName = client.CompanyName, LoanStatus = item.LoanStatus, JobNo = job.JobNo, JobFinancialYE = job.JobFinancialYE, VolumeNo = item.VolumeNo };
Why doesn't this return anything?
There two possibilites:
1) The join is empty, that is, no items, clients and jobs have matching ID's.
2) The where clause is false for all records in the join.
To troubleshoot this you will have to remove the where clause and/or some of the joined tables to see what it takes to get any results.

Categories