Adding new class member via LINQ query - c#

I have a LINQ query and because the variable that stores the result will be used in an "if" statement, I've had to initialize it before the query. This required making a class due to the different data types being stored in the list - however I'm having trouble making class members inside the LINQ query and I'm not sure why.
Class:
public class OtherProgramType
{
public string State { get; set; }
public string PrgName { get; set; }
public short? ProgramTypeID { get; set; }
public string DisplayText { get; set; }
}
Code:
List<OtherProgramType> otherPrograms;
otherPrograms = (from hm in db.HabitatManagement
join svy in db.Survey on hm.SurveyID equals svy.SurveyID
join iu in db.InventoryUsers on hm.UserID equals iu.UserID
join pt in db.ProgramType on hm.ProgramTypeID equals pt.ProgramTypeID
where pt.Program != "State Agency Public Land Programs"
&& pt.Program != "State Agency Private Land Programs"
&& svy.ReportingYear == (from svy in db.Survey
where svy.ReportingYear.HasValue
select svy.ReportingYear.Value).Max()
|| pt.Program != "State Agency Public Land Programs"
&& pt.Program != "State Agency Private Land Programs"
&& svy.ReportingYear == (from svy in db.Survey
where svy.ReportingYear.HasValue
select svy.ReportingYear.Value).Max() - 1
select new
{
iu.StateID,
hm.ProgramTypeID,
pt.Program
})
.Distinct()
.Select(x => new OtherProgramType { x.StateID, x.Program, x.ProgramTypeID, DisplayText = x.StateID.ToString() + ", " + x.Program.ToString() })
.OrderBy(x => x.StateID)
.ToList();
This is the line where I want the new class member to be made:
.Select(x => new OtherProgramType { x.StateID, x.Program, x.ProgramTypeID, DisplayText = x.StateID.ToString() + ", " + x.Program.ToString() })
The x.StateID, x.Program, x.ProgramTypeID get underlined in red squiggles and it says "Invalid initializer member declarator."

You need to state the field assignments, especially since the fields from x don't match the fields from your type OtherProgramType
.Select(x => new OtherProgramType
{
State = x.StateID,
PrgName = x.Program,
ProgramTypeID = x.ProgramTypeID,
DisplayText = x.StateID.ToString() + ", " + x.Program.ToString()
})

You need to give the names of the properties you want to assign to:
.Select(x => new OtherProgramType {
State = x.StateID,
PrgName = x.Program,
ProgramTypeID = x.ProgramTypeID,
DisplayText = x.StateID.ToString() + ", " + x.Program.ToString()
})

Both the above answers are absolutely correct. Just to add:
If your class had a constructor taking all the parameters your code could have been:
public class OtherProgramType
{
public OtherProgramType(string s, string pn, short? ptid, string dt)
{
this.State = s;
this.PrgName = pn;
this.ProgramTypeID = ptid;
this.DisplayText = dt;
}
public string State { get; set; }
public string PrgName { get; set; }
public short? ProgramTypeID { get; set; }
public string DisplayText { get; set; }
}
Now the appropriate line could be:
...
.Select(x => new OtherProgramType ( x.StateID, x.Program, x.ProgramTypeID, x.StateID.ToString() + ", " + x.Program.ToString() ))
...
Notice the () instead of {}.

Related

LINQ/C# - Making a DTO from a collection?

I'm using EF 6.2 with SQL. Suppose I have these DTO classes:
private class ParentModel
{
public string FullName { get; set; }
public IEnumerable<ChildModel> Children { get; set; }
}
private class ChildModel
{
public string FullName { get; set; }
public string SpiritAnimalDescription { get; set; }
}
ParentModel is derived from an entity class Parent.
ChildModel is from Child, which has a relationship with another entity class SpiritAnimal. Note that I changed it in the .EDMX to Children.
As you can infer, SpiritAnimal has a Description field which I'm trying to retrieve into the ChildModel field, SpiritAnimalDescription.
Naturally, a Parent has a collection of Child, which in turn has one SpiritAnimal (by design). Now, I'm trying to obtain a List<ParentModel> with this code, which currently isn't working:
var query = from p in db.Parents
join c in db.Children on p.Id equals c.Parent_Id
join sa in db.SpiritAnimals on c.SpiritAnimal_Id equals sa.Id
select new ParentModel
{
FullName = p.LastName + ", " + p.FirstName
Children = c.Select(a => new ChildModel // <-- Error here :(
{
FullName = a.FirstName + " " + a.LastName,
SpiritAnimalDescription = sa.Description
}
};
var list = query.ToList();
How can I solve this, as efficiently as possible? Thanks!
EDIT:
Entity classes look something like this, for brevity:
private class Parent
{
public int Id { get; set; } // PK
public string LastName { get; set; }
public string FirstName { get; set; }
}
private class Child
{
public int Id { get; set; } // PK
public string LastName { get; set; }
public string FirstName { get; set; }
public int Parent_Id { get; set; } // FK
public int SpiritAnimal_Id { get; set; } // FK
}
private class SpiritAnimal
{
public int Id { get; set; } // PK
public string Description { get; set; }
}
Your code cannot be compiled and run, so it is impossible to determine exactly what should be.
I can only assume that it should be something like this:
var query = from p in db.Parents
select new ParentModel
{
FullName = p.LastName + ", " + p.FirstName,
Children = db.Children.Where(c => c.Parent_Id == p.Id)
.Select(c => new ChildModel
{
FullName = c.FirstName + " " + c.LastName,
SpiritAnimalDescription = db.SpiritAnimals
.FirstOrDefault(sa => sa.Id == c.SpiritAnimal_Id).Description
})
};
Note: use the navigation properties.
Should look something like this:
var query = from p in db.Parents
select new ParentModel()
{
FullName = p.LastName + ", " + p.FirstName,
Children = p.Clildren.Select(a => new ChildModel()
{
FullName = a.FirstName + " " + a.LastName,
SpiritAnimalDescription = sa.Description
}).ToList()
};

Issue Related to SelectMany function in LINQ

I have two tables in Database:
PostCalculationLine
PostCaluclationLineProduct
PostCalculationLineProduct(table2) contains Foriegn key of PostCalucationLineId(table1)
In C# code I have two different Models for these two tables as follows:
public class PostCalculationLine : BaseModel
{
public long Id{ get; set; }
public string Position { get; set; }
public virtual Order Order { get; set; }
public virtual Task Task { get; set; }
//some other properties go here
public virtual IList<PostCalculationLineProduct> PostCalculationLineProducts { get; set; }
}
and
public class PostCalculationLineProduct : BaseModel
{
public long Id {get;set;}
public string Description { get; set; }
//some other properties go here
}
Now in Entityframework code, I fetch data from PostCalculationLineProduct as follows:
PostCalculationLineRepository pclr = new PostCalculationLineRepository();
DataSourceResult dsrResult = pclr.Get()
.SelectMany(p => p.PostCalculationLineProducts)
.Where(c => c.Product.ProductType.Id == 1 && c.DeletedOn == null)
.Select(c => new HourGridViewModel()
{
Id = c.Id,
Date = c.From,
EmployeeName = c.Employee != null ?c.Employee.Name:string.Empty,
Description= c.Description,
ProductName = c.Product != null?c.Product.Name :string.Empty,
From = c.From,
To = c.Till,
Quantity = c.Amount,
LinkedTo = "OrderName",
Customer ="Customer"
PostCalculationLineId = ____________
})
.ToDataSourceResult(request);
In the above query I want to get PostCalculationLineId(from Table1) marked with underLine. How can I achieve this?
Thanks
You can use this overload of SelectMany to achieve this:-
DataSourceResult dsrResult = pclr.Get()
.SelectMany(p => p.PostCalculationLineProducts,
(PostCalculationLineProductObj,PostCalculationLineObj) =>
new { PostCalculationLineProductObj,PostCalculationLineObj })
.Where(c => c.PostCalculationLineProductObj.Product.ProductType.Id == 1
&& c.PostCalculationLineProductObj.DeletedOn == null)
.Select(c => new HourGridViewModel()
{
Id = c.PostCalculationLineProductObj.Id,
Date = c.PostCalculationLineProductObj.From,
//Other Columns here
PostCalculationLineId = c.PostCalculationLineObj.Id
};
This will flatten the PostCalculationLineProducts list and returns the flattened list combined with each PostCalculationLine element.

How to Add Collection List to a List in Asp.net MVC

I am Executing two linq queries for employees and contractors in a method and Converting to List then i am bind to list seperately declared in the model class.
I am executing this method every time for each company from list of companies by passing company id and model class as parameters like
public void GetEmployeeContractorsTimesheetNotEntered(int COMP_ID, string COMPANY_NAME, TimesheetModel model)
{
context = new ResLandEntities();
DateTime todayDate = DateTime.Now.Date;
DateTime thisWeekStartDate = todayDate.AddDays(-(int)todayDate.DayOfWeek).Date; //Start Date of Current Week
DateTime thisWeekEndDate = thisWeekStartDate.AddDays(6); // End Date of Current Week
var todaysDay = (int)DateTime.Now.DayOfWeek;
var employeesNotEnteredTimesheetList = (from emps in context.EMPLOYEE
join comp in context.COMPANY on emps.COMP_ID equals comp.ID
join notify in context.NOTIFICATION on emps.NOTIFICATION_ID equals notify.ID
from week in context.WEEK_CALENDER
from statlk in context.STATUS_LKUP
where !context.TIMESHEET.Any(m => m.WEEK_CAL_ID == week.ID
&& m.RES_TYPE == "EMPLOYEE"
&& m.RES_ID == emps.ID
&& m.COMP_ID == COMP_ID
&& m.IS_DELETED=="N") &&
week.WEEK_START_DT.Month == DateTime.Now.Month &&
week.WEEK_START_DT.Year == DateTime.Now.Year &&
week.WEEK_END_DT<=thisWeekEndDate &&
statlk.TYPE == "TIMESHEET" &&
statlk.STATE == "NOT_ENTERED" &&
emps.IS_DELETED == "N" &&
emps.COMP_ID==COMP_ID
select new TimesheetModel
{
EMP_ID = emps.ID,
EMP_COMP_ID = emps.COMP_EMP_ID,
EMPLOYEE_NAME = emps.FIRST_NAME + " " + emps.LAST_NAME,
COMPANY_NAME = comp.NAME,
PrimaryEmail = notify.PRI_EMAIL_ID,
SDate = week.WEEK_START_DT,
EDate = week.WEEK_END_DT,
EMP_STATUS = "NOT_ENTERED"
}).Distinct().ToList();
//Adding a Collection of List Here
model.GetTimesheetNotEnteredDetails.AddRange(employeesNotEnteredTimesheetList.GroupBy(m => m.EMP_ID).Select(m => m.First()).ToList());
var contractorsNotEnteredTimesheetList = (from contrs in context.CONTRACTOR
join client in context.CLIENT on contrs.CLIENT_ID equals client.ID
join notification in context.NOTIFICATION on contrs.NOTIFICATION_ID equals notification.ID
from week in context.WEEK_CALENDER
from statlk in context.STATUS_LKUP
where !context.TIMESHEET.Any(m => m.RES_ID == contrs.ID
&& m.WEEK_CAL_ID == week.ID
&& m.COMP_ID == COMP_ID
&& m.RES_TYPE == "CONTRACTOR"
&& m.IS_DELETED == "N")
&& week.WEEK_START_DT.Month == DateTime.Now.Month
&& week.WEEK_START_DT.Year == DateTime.Now.Year
&& statlk.STATE == "NOT_ENTERED"
&& statlk.TYPE == "TIMESHEET"
&& contrs.IS_DELETED == "N"
&& week.WEEK_START_DT <= thisWeekEndDate
&& contrs.COMP_ID == COMP_ID
select new TimesheetModel
{
EMP_ID=contrs.ID,
EMPLOYEE_NAME = contrs.FIRST_NAME + " " + contrs.LAST_NAME,
COMPANY_NAME = COMPANY_NAME,
SDate=week.WEEK_START_DT,
EDate=week.WEEK_END_DT,
CLIENT_NAME = client.NAME,
PrimaryEmail = notification.PRI_EMAIL_ID
}).Distinct().ToList();
//Adding Collection of List Here
model.GetContractorNotEnteredDetails .AddRange(contractorsNotEnteredTimesheetList.GroupBy(m => m.EMP_ID).Select(m => m.First()).ToList());
}
Now, my problem is I want to add list collection separately to two list, though i am binding the list separately , the two results of employees and contractors lists are clubbing in two lists like employees and contractors are in binding the two lists instead it should bind separately. whats going wrong, is it "AddRange" should not use for binding collection list to one list, is there any way for this solution, please help me anyone.
use this
var props = typeof(TimesheetModel).GetProperties();
DataTable dt= new DataTable();
dt.Columns.AddRange(
props.Select(p => new DataColumn(p.Name, p.PropertyType)).ToArray()
);
employeesNotEnteredTimesheetList.ForEach(
i => dt.Rows.Add(props.Select(p => p.GetValue(i, null)).ToArray())
);
var list1 = (from p in dt.AsEnumerable()
select p).ToList();
//similar for second list
Finally Got it.
Just I have separated Accessors in different Classes like
public class EmployeeTimesheetDetails
{
public int EMP_ID { get; set; }
public string EMP_COMP_ID { get; set; }
public string EMPLOYEE_NAME { get; set; }
public string COMPANY_NAME { get; set; }
public string PrimaryEmail { get; set; }
public DateTime SDate { get; set; }
public DateTime EDate { get; set; }
public string EMP_STATUS { get; set; }
}
public class ContractorsTimesheetDetails
{
public int CONTR_ID { get; set; }
public string CONTRACTOR_NAME { get; set; }
public string COMPANY_NAME { get; set; }
public DateTime SDate { get; set; }
public DateTime EDate { get; set; }
public string CLIENT_NAME { get; set; }
public string PrimaryEmail { get; set; }
}
and modified the two list in model class like
public List<EmployeeTimesheetDetails> GetTimesheetNotEnteredDetails { get; set;}
public List<ContractorsTimesheetDetails> GetContractorNotEnteredDetails { get; set; }
This modification is cleared my issue .
You need to have two properties in the class TimesheetModel, something like this:
public class CompanyListModel
{
public List<CompanyModel> CompanyList { get; set; };
}
public class CompanyModel
{
public List<TimesheetModel > EmployeesNotEnteredTimesheetList { get; set; };
public List<TimesheetModel > ContractorsNotEnteredTimesheetList { get; set; };
}
Then add like this:
public void GetEmployeeContractorsTimesheetNotEntered(int COMP_ID, string COMPANY_NAME, CompanyListModel model)
{
// your stuff
CompanyModel conpanyModel = new CompanyModel();
conpanyModel.EmployeesNotEnteredTimesheetList = employeesNotEnteredTimesheetList.GroupBy(m => m.EMP_ID).Select(m => m.First()).ToList();
conpanyModel.ContractorsNotEnteredTimesheetList = contractorsNotEnteredTimesheetList.GroupBy(m => m.EMP_ID).Select(m => m.First()).ToList();
model.CompanyList.add(companyModel);
// your stuff
}

How to avg() in linq

I'm trying write my sql commang to Linq:
SQL:
select avg(sub.evaluation) from submit_task sub where student_id='" + idStudent + "' and state='close';
Linq:
double avg = (ado.submit_task.Where(r => (r.id == idStudent && r.state == "close")).Average(r => r.evaluation));
avgStudent = avg.ToString();
but this is not working, when I delete && r.state == "close" statement, I got result, but it's incorrect.
thank you.
I have tried the same with a sample set of data and it works fine
List<student> students = new List<student>
{
new student{id="1",state="close",evaluation=5},
new student{id="1",state="close",evaluation=4}
};
double avg = (students.Where(r => (r.id == "1" && r.state == "close")).Average(r => r.evaluation));
public class student
{
public string id { get; set; }
public string state { get; set; }
public int evaluation { get; set; }
}
may be you should check the data in the db or modify the state="close" part of the query
ok, here's code, which working:
var avgEvalClose = (from sub in ado.submit_task
where sub.student_id.Equals(idStudent)
where sub.state.Equals("close")
select sub.evaluation).Average();
avgStudent = avgEvalClose.ToString();

LINQ Querying list in list

I have this situation:
My ModelView:
public class Subject
{
public int ID { get; set; }
public string Name { get; set; }
public int ProfessorID { get; set; }
public string ProfessorFullName{ get; set; }
public IList<Assistant> Assistants { get; set; }
}
public class Assistant
{
public string AssistantFullName{ get; set; }
}
My query:
var subjects = from subject in Entities.Subjects
from professor in subject.Lecturers
where professor.Professor == true
select new SSVN.ModelView.Subject()
{
ID = subject.ID,
Name= subject.Name,
ProfessorFullName= professor.LastName+ " " + professor.Name,
Assistants= (from subject1 in Entities.Subjects
from assistant in subject1.Lecturers
where assistant.Professor == false
select new SSVN.ModelView.Assistant()
{
AssistantFullName = assistant.LastName+ " " + assistant.Name
}).ToList()
};
And when I call:
subjects.ToList(); I get exception:
LINQ to Entities does not recognize the method
'System.Collections.Generic.List`1[SSVN.ModelView.Assistant] ToList[Assistant]
(System.Collections.Generic.IEnumerable`1[SSVN.ModelView.Assistant])' method, and this
method cannot be translated into a store expression.
You cannot call ToList inside linq-to-entities query. Linq-to-entities query will always project to IEnumerable<T> so if you want IList<T> you must call it in linq-to-objects.
Try this:
var subjects = (from subject in Entities.Subjects
from professor in subject.Lecturers
where professor.Professor == true
select new
{
ID = subject.ID,
Name= subject.Name,
ProfessorFullName= professor.LastName+ " " + professor.Name,
Assistants= (from subject1 in Entities.Subjects
from assistant in subject1.Lecturers
where assistant.Professor == false
select new SSVN.ModelView.Assistant()
{
AssistantFullName = assistant.LastName+ " " + assistant.Name
})
}).AsEnumerable().Select(x => new SSVN.ModelView.Subject
{
ID = x.ID,
Name = x.Name,
ProfessorFullName = X.ProffesorFullName,
Assistants = x.Assistants.ToList()
});
You cannot and should not use a ToList() in an IQueryablle query. Note that this query has to be translated into SQL.

Categories

Resources