Create objects into model foreach query - c#

I have a simple model like:
public class StatisticsModel
{
public Guid TaskId { get; set; }
public string Name { get; set; }
public int Time {get; set; }
}
Now I want to add to that model each register of foreach clause like:
StatisticsModel model = new StatisticsModel();
foreach(var i in tasks)
{
var parameters = ToDataTable(tasks.Select(x => new { i.TaskId, i.Name }).ToList());
var timeOfTasks = db.ExeSQLParamTable("usp_Get_WorkedProyectTime", parameters, "#ProjectTimeWorkedTableType");
var test = (from DataRow dr in timeOfTasks.Rows select (int)dr["TaskName"]).FirstOrDefault();
model.TaskId = i.TaskId;
model.Name = i.Name;
model.Time = test
}
var final2 = model;
So as you can see I assign TaskId, Name and Time to model, but when foreach finish it only add last register to model. How can I create one object foreach task(in my case) in model? I try something like model.Add()but add method donesn't exists in my model. What am I doing wrong? Regards

You're close, you just need a list of models:
List<StatisticsModel> models = new List<StatisticsModel>();
foreach(var i in tasks)
{
StaticsModel model = new StatisticsModel();
var parameters = ToDataTable(tasks.Select(x => new { i.TaskId, i.Name }).ToList());
var timeOfTasks = db.ExeSQLParamTable("usp_Get_WorkedProyectTime", parameters, "#ProjectTimeWorkedTableType");
var test = (from DataRow dr in timeOfTasks.Rows select (int)dr["TaskName"]).FirstOrDefault();
model.TaskId = i.TaskId;
model.Name = i.Name;
model.Time = test;
models.Add(model);
}

You can't add multiple attributes to a single thing: you must have multiple StatisticsModel objects for this.
For example, you could use a List<StatisticsModel>:
var models = List<StatisticsModel>();
foreach(var i in tasks) {
StatisticsModel model = new StatisticsModel();
var parameters = ToDataTable(tasks.Select(x => new { i.TaskId, i.Name }).ToList());
var timeOfTasks = db.ExeSQLParamTable("usp_Get_WorkedProyectTime", parameters, "#ProjectTimeWorkedTableType");
var test = (from DataRow dr in timeOfTasks.Rows select (int)dr["TaskName"]).FirstOrDefault();
model.TaskId = i.TaskId;
model.Name = i.Name;
model.Time = test;
models.Add(model);
}
If you prefer LINQ-style queries, you could eliminate the loop altogether:
var models = tasks.Select(i => {
var parameters = ToDataTable(tasks.Select(x => new { i.TaskId, i.Name }).ToList());
var timeOfTasks = db.ExeSQLParamTable("usp_Get_WorkedProyectTime", parameters, "#ProjectTimeWorkedTableType");
var test = (from DataRow dr in timeOfTasks.Rows select (int)dr["TaskName"]).FirstOrDefault();
return new StatisticsModel {
TaskId = i.TaskId
, Name = i.Name
, Time = test
};
}).ToList();

Sounds like you need a List<StatisticsModel> at the top, that way you can add to it in your foreach:
List<StatisticsModel> models = new List<StatisticsModel>();
foreach(...)
{
...
StatisticsModel model = new StatisticsModel();
// Assign props
models.Add(model);
}
Or even better; since you are actually just transforming the task collection, just use a select:
List<StatisticsModel> models = tasks.Select(task => {
//The foreach contents
StatisticsModel model = new StatisticsModel();
// Assign props
return model;
}).ToList(); //ToList not necessary; eager enumeration is not ideal most of the time but included since you seem to want a list

Each iteration of your foreach loop overwrites the model. Store it in a List:
List<StatisticsModel> allModels = new List<StatisticsModel>();
foreach(var i in tasks)
{
StatisticsModel model = new StatisticsModel();
var parameters = ToDataTable(tasks.Select(x => new { i.TaskId, i.Name }).ToList());
var timeOfTasks = db.ExeSQLParamTable("usp_Get_WorkedProyectTime", parameters, "#ProjectTimeWorkedTableType");
var test = (from DataRow dr in timeOfTasks.Rows select (int)dr["TaskName"]).FirstOrDefault();
model.TaskId = i.TaskId;
model.Name = i.Name;
model.Time = test
allModels.Add(model);
}
var final2 = allModels;

you need to create a list (or some other collection) to get a list of the models. Here's the code below
List<StatisticsModel> models = new List<StatisticsModel>();
foreach(var i in tasks)
{
var parameters = ToDataTable(tasks.Select(x => new { i.TaskId, i.Name }).ToList());
var timeOfTasks = db.ExeSQLParamTable("usp_Get_WorkedProyectTime", parameters, "#ProjectTimeWorkedTableType");
var test = (from DataRow dr in timeOfTasks.Rows select (int)dr["TaskName"]).FirstOrDefault();
StatisticsModel model = new StatisticsModel();
model.TaskId = i.TaskId;
model.Name = i.Name;
model.Time = test
models.Add(model);
}
var final2 = models; //list of model

Related

How Can I pass a Data list to CreateAsync Func?

I have a problem with CreateAsync, it wants IOrderedQueryable.
I need to read just two records (Id,Title) from my News table and pass them to my ViewModel but it doesn't let me pass RetValue (list type) in CreateAsync.
var MyNews = _context.News.Select(news => new
{
news.Id,
news.Title,
}).AsNoTracking().OrderByDescending(p => p.Id);
List<ListNewsViewModel> RetValue = new List<ListNewsViewModel>();
foreach (var item in MyNews)
{
ListNewsViewModelLN = new ListNewsViewModel();
LN.Id = item.Id;
LN.Title = item.Title;
RetValue.Add(LN);
}
var model = await PagingList.CreateAsync(RetValue, 10, PageIndex);
model.Action = "EditNews";
return View(model);
You can try to do like this:
var MyNews = (from q in _context.News
select new ListNewsViewModel()
{
Id = q.Id;
Title = q.Title;
})
.AsNoTracking()
.OrderByDescending(p => p.Id);
var model = await PagingList.CreateAsync(MyNews, 10, PageIndex);
model.Action = "EditNews";
return View(model);
You pass a List<T> Which is not IQueryable But IEnumerable.
Pass the query result directly:
var MyNews = _context.News.Select(news => new ListNews
{
Id = news.Id,
Title = news.Title,
}).AsNoTracking().OrderByDescending(p => p.Id);
var model = await PagingList.CreateAsync(MyNews, 10, PageIndex);
model.Action = "EditNews";
return View(model);

How to convert Linq result to viewmodel

while filling a combobx, I need to convert a Linq-result to a viewmodel.
Actually, I query the records and then I fill a list of the viewmodel in a loop, but that seems to be a bit strange:
public static IEnumerable<ComboBoxActivities> GetActivitySelectList()
{
using(ApplicationDbContext db = new ApplicationDbContext())
{
var result = from activity in db.Activities
where activity.Available
select new
{
ActivityId = activity.Id,
ActivityName = activity.ActivityName,
Available = activity.Available
};
List<ComboBoxActivities> list = new List<ComboBoxActivities>();
foreach(var res in result)
{
ComboBoxActivities listItem = new ComboBoxActivities()
{
ActivityId= res.ActivityId,
ActivityName= res.ActivityName,
Available= res.Available
};
list.Add(listItem);
}
return list;
}
}
Is this really the right way?
I also tried:
var result = from activity in db.Activities
where activity.Available
select new ComboBoxActivities()
{
ActivityId = activity.Id,
ActivityName = activity.ActivityName,
Available = activity.Available
};
But then my razorview crashes with the message that direct binding to a quers (DbSet, DbQuery...) is not supported.
You can convert the IEnumerable<T> to a List<T> by using ToList()
public static List<ComboBoxActivities> GetActivitySelectList()
{
using(ApplicationDbContext db = new ApplicationDbContext())
{
var result = from activity in db.Activities
where activity.Available
select new ComboBoxActivities()
{
ActivityId = activity.Id,
ActivityName = activity.ActivityName,
Available = activity.Available
};
return result.ToList();
}
}
As for loading a ComboBox from a table query, ComboBox has a DataSource property which you can assign the List to.

StringBuilder within IEnumerable

I have a ControlMeasure table that holds information on each control measure and a ControlMeasurepeopleExposed Table that holds a record for each person exposed in the control measure this could be 1 record or many records.
I Have a controller that populates a List view
For each item in the list, Control Measure, I would like to create a string that shows all the People at risk
e.g.
PeopleString = "Employees, Public, Others";
Ive added a foreach in the controller to show what I'm trying to do however I'm aware that this wont work.
The controller is this:
public ActionResult ControlMeasureList(int raId)
{
//Populate the list
var hazards = new List<Hazard>(db.Hazards);
var controlMeasures = new List<ControlMeasure>(db.ControlMeasures).Where(x => x.RiskAssessmentId == raId);
var cmcombined = (
from g in hazards
join f in controlMeasures
on new { g.HazardId } equals new { f.HazardId }
select new CMCombined
{
Activity = f.Activity,
ControlMeasureId = f.ControlMeasureId,
ExistingMeasure = f.ExistingMeasure,
HazardName = g.Name,
LikelihoodId = f.LikelihoodId,
Rating = f.Rating,
RiskAssessmentId = f.RiskAssessmentId,
SeverityId = f.SeverityId,
}).OrderBy(x => x.Activity).ToList();
var cmPeopleExp = new List<ControlMeasurePeopleExposed>(db.ControlMeasurePeopleExposeds).Where(x => x.RiskAssessmentId == raId);
var peopleExp = from c in cmPeopleExp
join d in db.PeopleExposeds
on c.PeopleExposedId equals d.PeopleExposedId
orderby d.Name
select new RAPeopleExp
{
RAPeopleExpId = c.PeopleExposedId,
PeopleExpId = c.PeopleExposedId,
PeopleExpName = d.Name,
RiskAssessmentId = c.RiskAssessmentId,
ControlMeasureId = c.ControlMeasureId
};
var model = cmcombined.Select(t => new FullControlMeasureListViewModel
{
ControlMeasureId = t.ControlMeasureId,
HazardName = t.HazardName,
LikelihoodId = t.LikelihoodId,
Rating = t.Rating,
SeverityId = t.SeverityId,
Activity = t.Activity,
ExCM = t.ExistingMeasure,
//This section here is where I'm struggling
var PeopleString = new StringBuilder();
foreach (var p in peopleExp)
{
PeopleString.AppendLine(p.PeopleName);
{
PeopleExposed = PeopleString,
});
return PartialView("_ControlMeasureList", model);
}
I know I cant directly put this code in the controller but it does represent what I want to do.
You can't foreach within an object initializer (which is what you're trying to do when instantiating FullControlMeasureListViewModel). You can, however, use a combination of string.Join and peopleExp.Select:
var model = cmcombined.Select(t => new FullControlMeasureListViewModel
{
//other props
PeopleExposed = string.Join(",", peopleExp
.Where(p => p.ControlMeasureId == t.ControlMeasureId)
.Select(p => p.PeopleExpName));
//other props
});

Insert data from one sql table row to another where field matches - Entity Framework

I have two tables in an SQL database. They both have five fields: ID (PK), Number, InvoiceDate, InvoiceNumber, and InvoiceAmount. I am attempting to use Entity Framework to insert the InvoiceDate, InvoiceNumber, and InvoiceAmount where the field Number matches from one table to the other.
The context for table one is:
var tc = new TemporaryCsvUpload();
Table two:
var pt = new PermanentTestTable();
First, I inserted values into table 1 from a CSV, now I am trying to insert into table two where the Number field matches.
var entity = new CsvDbEntities1();
foreach (var item in model)
{
var tc = new TemporaryCsvUpload();
tc.Number = item.Number;
tc.CreditInvoiceAmount = item.CreditInvoiceAmount;
tc.CreditInvoiceDate = item.CreditInvoiceDate;
tc.CreditInvoiceNumber = item.CreditInvoiceNumber;
entity.TemporaryCsvUploads.Add(tc);
entity.SaveChanges();
}
I am new to EF and any help would be appreciated. Thanks!
Sorry if I dont completely understand but here it goes based of this code :
foreach (var item in model)
{
var tc = new TemporaryCsvUpload();
tc.Number = item.Number;
tc.CreditInvoiceAmount = item.CreditInvoiceAmount;
tc.CreditInvoiceDate = item.CreditInvoiceDate;
tc.CreditInvoiceNumber = item.CreditInvoiceNumber;
entity.TemporaryCsvUploads.Add(tc);
entity.SaveChanges();
}
After you have saved the first table now you query the second for the same record as :
var table2entity = entity.PermanentTestTable.Where(x => x.Number == tc.Number).Select(x => x).First();
This will query the second table and grab whatever entity is there with the same number
So your end code might look like :
var entity = new CsvDbEntities1();
foreach (var item in model)
{
var tc = new TemporaryCsvUpload();
tc.Number = item.Number;
tc.CreditInvoiceAmount = item.CreditInvoiceAmount;
tc.CreditInvoiceDate = item.CreditInvoiceDate;
tc.CreditInvoiceNumber = item.CreditInvoiceNumber;
entity.TemporaryCsvUploads.Add(tc);
entity.SaveChanges();
var table2entity = entity.PermanentTestTable.ToList();
table2entity = table2entity.Where(x => x.Number == tc.Number).Select(x => x).First();
table2entity.CreditInvoiceAmount = item.CreditInvoiceAmount;
//More values inserted here
entity.SaveChanges()
}
I ended up having to nest a foreach loop to iterate through every row with a Number field. I'm sure there is a better way to do this, but I am just happy it's working:
var entity = new CsvDbEntities1();
foreach (var item in model)
{
var tc = new TemporaryCsvUpload
{
PoNumber = item.Number,
CreditInvoiceAmount = item.CreditInvoiceAmount,
CreditInvoiceDate = item.CreditInvoiceDate,
CreditInvoiceNumber = item.CreditInvoiceNumber
};
entity.TemporaryCsvUploads.Add(tc);
var ptt = entity.PermanentTestTables.ToList().Where(x => x.Number == tc.Number);
foreach (var row in ptt)
{
row.CreditInvoiceDate = tc.CreditInvoiceDate;
row.CreditInvoiceNumber = tc.CreditInvoiceNumber;
row.CreditInvoiceAmount = tc.CreditInvoiceAmount;
}
entity.SaveChanges();
}

How merge two sequences into one?

I have some working code that retrieves data from data base. It is interesting for me to get some better code for my solution. Are there some ways to combine two queries into one or something like this?
Dim customerTitlesAndIDs = contex.CustomerTable.Select(Function(row) New
With {.ID = row.ID, .CustomerTitle = row.Title}).ToList()
Dim cutomerIdPayment = contex.CustomerPayments.Select(Function(table) New
With
{
.ID = table.CustomerID,
.Range = table.PaymentsRange,
.Values = table.Values
}).ToList()
Dim customerInfos As New List(Of SCustomerInfo)
For Each customer In customerTitlesAndIDs
Dim cID As Integer = customer.ID
customerInfo.Add(New SCustomerInfo(CreateCustomerTable(), cID, customer.CustomerTitle))
For Each cutomerPayments In cutomerIdPayment
If cutomerPayments.ID = cID Then
Dim rangeValue(1) As Object
rangeValue(0) = cutomerPayments.Range
rangeValue(1) = cutomerPayments.Values
Dim dtRow As DataRow = customerInfos.Last().PaymentTable.NewRow()
dtRow.ItemArray = rangeValue
customerInfos.Last().PaymentTable.Rows.Add(dtRow)
End If
Next
Next
Return customerInfos
Same code with C# (hope no syntax errors occurred):
var customerTitlesAndIDs = contex.CustomerTable.Select(row => new
{ .ID = row.ID, .CustomerTitle = row.Title }).ToList();
var cutomerIdPayment = contex.CustomerPayments.Select(table => new
{
.ID = table.CustomerID,
.Range = table.PaymentsRange,
.Values = table.Values
}).ToList();
List<SCustomerInfo> customerInfos = new List<SCustomerInfo>;
foreach (var customer in customerTitlesAndIDs)
{
int cID = customer.ID;
customerInfos.Add(new SCustomerInfo(CreateCustomerTable(), cID, customer.CustomerTitle));
foreach (var cutomerPayments in cutomerIdPayment)
{
if (cutomerPayments.ID = cID)
{
object[] rangeValue = new object[1] {cutomerPayments.Range, cutomerPayments.Values};
DataRow dtRow = customerInfos.Last().PaymentTable.NewRow();
dtRow.ItemArray = rangeValue;
customerInfos.Last().PaymentTable.Rows.Add(dtRow);
}
}
}
SCustomerInfo represented by folowing Structure (code is simplified):
Public Structure SWindAltitude
Public PaymentTableAs DataTable
Public Title As String
Public ID As Integer
End Structure
Both C# and VB.NET solutions will be helpful.
Try something like this, utilizing navigation properties (you'll probably have to massage it as I don't know the exact makeup of your data structures):
var customerQuery = context.CustomerTable.Select( ct =>
new {
ct.ID,
ct.CustomerTitle,
// use nav property to get customer payments
CustomerPayments = ct.CustomerPayments.Select( cp =>
new {
Range = cp.Range,
Values = cp.Values } ) } );
return customerQuery.ToArray()
.Select( cq =>
{
var retVal = new SCustomerInfo( CreateCustomerTable(), cq.ID, cq.CustomerTitle );
foreach( var customerPayment in cq.CustomerPayments )
{
var dtRow = cq.PaymentTable.NewRow();
dtRow.ItemArray = new object[] { customerPayment.Range, customerPayment.Values };
retVal.PaymentTable.Rows.Add( dtRow );
}
return retVal;
} );
if i understand right in c# with linq it will be something like this
var customerInfos = customerTitlesAndIDs.Select((c)=>{
var ci = new SCustomerInfo(CreateCustomerTable(), c.ID, customer.CustomerTitle);
ci.PaymentTable = ci.PaymentTable.AsEnumerable().Union(
cutomerIdPayment.Where(j=>j.ID == c.ID)
.Select(j=>{
var dtRow = ci.PaymentTable.NewRow();
dtRow.ItemArray = new object[] {
customerPayment.Range,
customerPayment.Values
};
return dtRow;
})).CopyToDataTable();
return ci;
}).ToList();
I think you can use the Linq provided function Sequence.concat() as described here: http://msdn.microsoft.com/en-us/library/vstudio/bb386979(v=vs.100).aspx

Categories

Resources