Groupby in c# to Add in new list - c#

I have a filtered data according to date and group it according to document type and count it like:
Data1 - Memo
Data2 - Lett
Data3 - Memo
Data4 - Case
Output
Memo - 2
Lett - 1
Case - 1
I don't know if I'm doing it right. I can't display the output to View
Model--
public class ViewModelIndexTransfiles
{
public int Count { get; set; }
public string idoctype { get; set; }
public List<TransFile> transPrint { get; set; }
public List<TransFile> summary { get; set; }
}
Controller--
modelPrint.transPrint = db.TransFiles.Where(s => (s.tfl_idetype == selectedtrstyp) &&
(DbFunctions.TruncateTime(s.tfl_update) >= modelPrint.dteFrom.Date &&
DbFunctions.TruncateTime(s.tfl_update) <= modelPrint.dteTo.Date)).ToList();
//This one is good as I was able to filter the data first according to date and display the data using modelPrint.transPrint
var doccount = modelPrint.transPrint.GroupBy(o => o.tfl_idoctype).Select(x =>
new { tfl_idoctype = x.Key, Count = x.Count() }).ToList();
// this one is the grouped data. I don't know what is next to this so I can display the desired output or pass it to view.
return View(modelPrint);
// I don't know which is to return :(
View--
#foreach (var member in Model.summary)
{
<tr>
<td>Document Type</td>
<td>Count</td>
</tr>
}
I tried this code before the return, but It's not working.
for (int i = 0; i < doccount.ToList().Count; i++)
{
modelPrint.summary.Add(
new ViewModelIndexTransfiles
{
idoctype = doccount[i].tfl_idoctype,
Count = doccount[i].Count
});
What am I missing?

Related

Return Multiple View Model data to HTML view

In my web application, there are two types of data I need to show in the html view in different tables.
So First I created two different view models to store data.
So in the controller I have wrote this code to send the data to view models
List < RecognizedPartsViewModel > Reco = new List < RecognizedPartsViewModel > ();
var rData = (from i in db.InventoryMain join p in db.PartCategory on i.PartCatogary equals p.Id where i.ReOrderQty != 0 && i.AvaQty <= i.ReOrderQty && i.PartCatogary != 0 select new RecognizedPartsViewModel {
PartNo = i.PartNo,
Description = i.PartDescription,
Model = i.PartModel,
AvaQty = i.AvaQty,
ReOrderQty = i.ReOrderQty,
PartCato = i.PartCatogary,
ABCD = i.A_B_C_D_Category
}).ToList();
List < UnRecoPartsViewModel > unReco = new List < UnRecoPartsViewModel > ();
var rUnData = (from i in db.InventoryMain where i.ReOrderQty != 0 && i.AvaQty <= i.ReOrderQty && i.PartCatogary == 0 select new UnRecoPartsViewModel {
PartNo = i.PartNo,
Description = i.PartDescription,
Model = i.PartModel,
AvaQty = i.AvaQty,
ReOrderQty = i.ReOrderQty,
ABCD = i.A_B_C_D_Category
}).ToList();
So I need to know that this data I have to show in the same html view. So how can I call these two view model as separate list in the html view?
If your data model has structure described in the question you can use the one class for two cases:
public class PartsViewModel
{
public string PartNo { get; set; }
public string Description { get; set; }
public string Model { get; set; }
public int AvaQty { get; set; }
public int ReOrderQty { get; set; }
public string PartCato { get; set; } // Used only in the a table for RecognizedParts
public string ABCD { get; set; }
}
And then create a new class to included separated list for each category:
public class PartsDataModel
{
public List<PartsViewModel> RecognizedParts { get; set; }
public List<PartsViewModel> UnRecognizedParts { get; set; }
}
Then:
public ActionResult Index()
{
// ... copy your previous code here, but use `PartsDataModel` class
// instead of `RecognizedPartsViewModel `UnRecoPartsViewModel`.
var model = new PartsDataModel()
{
RecognizedParts = rData,
UnRecognizedParts = rUnData
}
// Create the view
return View(model);
}
You need to create another model that can take both types of data, that is 1 List < RecognizedPartsViewModel > and 1 List < UnRecoPartsViewModel > and you would pass this model to your view and access each one of your lists using this model

How to count rows of a table grouped by shortdatestring?

We have an database with an this structure:
public partial class ChartData
{
public int Id { get; set; }
public DateTime Timestamp { get; set; }
public string Function { get; set; }
public int Duration { get; set; }
public bool IsError { get; set; }
}
Now we want to group the entries of this database by Timestamp.ToShortDateString() and then count the entries belonging to this date.
So for example we have:
2019-06-04 11:54:02,135,someFunction,30,False,
2019-06-04 11:55:03,135,someFunction,230,False,
2019-06-04 11:56:03,150,someFunction,4,True,
2019-06-05 11:54:03,230,someFunction,46,False,
2019-06-05 11:55:03,230,someFunction,46,False,
And I want this result:
{date: 2019-06-04, rows: 3}
{date: 2019-06-05, rows: 2}
public List <LogFileDTO> GetLogFilesData()
{
var items = db.ChartDatas.GroupBy(x = > new {
x.Timestamp.ToShortDateString
}).Select(x = > new LogFileDTO {
date = x.Timestamp.First(),
rows = x.Count ?
}).ToList();
}
So I do not really know how to group this input by date and then count the rows of each group.
You simply need to group on the Date property of the TimeStamp and then project using Select on the Key of each IGropuing and Count like below :
var items = db.ChartDatas.GroupBy(x => x.Timestamp.Date) // group only on Date
.Select(x => new LogFileDTO
{
Date = x.Key.ToShortDateString(),
Rows = x.Count()
}).ToList();
Key will contain only date part of DateTime object and Count() will tell the number of rows for that date in the group.
Hope it helps!

How cani write Linq Query for getting Record over multipul times

Here I create one class FatClass:
public class Ems_UserFat_Tab
{
public string Hr_Email { get; set; }
public string BuHead_Email { get; set; }
My table is
Id Email RoleId
1 abc#gmail.com 2
2 lmn#gmail.com 3
Linq Query as
var x = from n in db.EMS_USER_MASTER
where n.ROLE_ID == 2 || n.ROLE_ID==3
select new Ems_UserFat_Tab
{
Hr_Email = n.EMAIL,
BuHead_Email=n.EMAIL
};
Here how can I differentiate ROLE_ID=2 email and ROLE_ID=3 email in this query
public void OnNext()
{
var x = list.Where(ro => ro.roleID = 2 && ro.roleID = 3)
.Select(ro => new CacheObject
{
Hr_Email = ro.EMAIL,
BuHead_Email=ro.EMAIL
});
}
You have to store those values in Cache or to evoke them from DB ,which will be your object like in the example new CacheObject. Try to do it like this and debug it.

Ordering int values orders 11,12,13 before 2

In my Sql table the index primary key is an integer (1,2,3,...)
I have an Entity query like this :
var pagedQAs = getAllQAs
.Where(qa => qa.Show)
.OrderByDescending(qa => qa.Code)
.Skip((page - 1) * pageSize).Take(pageSize)
.Select(QAViewModels.Set)
.ToList();
And the result sorted list is like this:
1
11
12
...
2
21
22
...
3
31
32
...
What should be right to show correct ordered numbers?
Edit>>>
Table in sql :
Table in sql
The project is Model First Not Code First
The model :
public class QAViewModels
{
public int Code { get; set; }
public string Question { get; set; }
public string InquirerName { get; set; }
public string InquirerEmail { get; set; }
public int VisitCounts { get; set; }
public Nullable<int> Respondent { get; set; }
public Nullable<System.DateTime> RespondDate { get; set; }
public string Answer { get; set; }
public string AnswerSummary { get; set; }
public virtual BaseMember BaseMember { get; set; }
public static QAViewModels Set(QuestionAnswer qa)
{
return new QAViewModels
{
Code = qa.Code,
Question = qa.Question,
InquirerName = qa.InquirerName,
InquirerEmail = qa.InquirerEmail,
VisitCounts = qa.VisitCounts,
Respondent = qa.Respondent,
RespondDate = qa.RespondDate,
Answer = qa.Answer,
AnswerSummary = qa.AnswerSummary,
BaseMember = qa.BaseMember
};
}
}
All types are based on SQL table fileds data type
The Store :
public List<QAViewModels> GetAllRawPaged(int page, int pageSize, out int count)
{
var getAllQAs = Tools.DataModel.QuestionAnswers;
count = getAllQAs.Count();
var pagedQAs = getAllQAs
.Where(qa => qa.Show)
.OrderByDescending(qa => qa.Code)
.Skip((page - 1) * pageSize).Take(pageSize)
.Select(QAViewModels.Set)
.ToList();
return pagedQAs;
}
Actions and queries on data stored in QAStore
The Controller :
public ActionResult CM_QAs()
{
QAStore qas = new QAStore();
int count = 0;
LabelStore ls = new LabelStore();
List<TagsViewsModel> tags = ls.GetAllTags();
List<QAViewModels> allQAs = qas.GetAllRawPaged(1, 100, out count);
return View(allQAs);
}
Get all QuestionAnswers and pass to view
The View :
#model List<wrrc.Models.QAViewModels>
<div>
#foreach (var qa in Model)
{
<div>
<span>
<span>Question Number
#Tools.ConvertNumerals(Convert.ToString(qa.Code))
</span>
</span>
<div>#Html.Raw(qa.Question)</div>
<div>#Tools.TruncateAtWord(qa.Answer, 500)))</div>
<a href="#Url.Action("SingleQA", "QA" >Full Description</a>
</div>
}
</div>
You should sort the Code as int;
var pagedQAs = getAllQAs
.Where(qa => qa.Show)
.ToList()
.OrderByDescending(qa => int.Parse(qa.Code))
.Skip((page - 1) * pageSize).Take(pageSize)
.Select(QAViewModels.Set)
.ToList();
Also, It could be better to prevent possible null values or incorrect strings to parse integer;
int val = 0;
var pagedQAs = getAllQAs
.Where(qa => qa.Show)
.ToList()
.OrderByDescending(qa => int.TryParse(qa.Code,out val) ? val : Int32.MaxValue)
.Skip((page - 1) * pageSize).Take(pageSize)
.Select(QAViewModels.Set)
.ToList();
Also, with this query you should perform order/skip/take actions on the client side. int.TryParse or int.Parse can't be translated to sql query in IQueryable form. So, if you have a chance to modify Code column as int in the database, it could be better solution.

LINQ to iterate through IEnumerable and set duplicates to null

I have an IEnumerable
IEnumerable<Pets> pets;
It consists of
public string Name { get; set; }
public string Other { get; set; }
public decimal? Price { get; set; }
I want to iterate through this and find all prices that are duplicate and set those duplicate prices to null.
Say A cat and a Dog have same price: 10.55. I want to keep first one but remove all remaining prices.
Ways:
1) Remove duplicates (I recommend it):
var filtered = pets.GroupBy(pet => pet.Price).Select(group => group.First());
2) Sort & evalute - set null in place of duplicates as you wish (Are you sure that you want to set nulls instead of removing like in 1) ?).
var newPets = pets.OrderBy(per => pet.Price).ToList();
if (!newPets.Any()) return newPets;
var last = 0;
for (var i = 1; i < newPets.Count; i++)
{
if (newPets[i].Price == newPets[last].Price) newPets[i] = null;
else last = i;
}
return newPets;
I think that ordering is sufficient in that case: O(n * log n) + O(n) against O(n^2) in custom iterates to search duplicates for each element.
3) Classic way (without sorting, slowest)
var newPets = pets.ToList();
for (var i = 0; i < newPets.Count; i++)
{
if (newPets[i] == null) continue;
var price = newPets[i].Price;
for (var j = i + 1; j < newPets.Count; j++)
{
if (newPets[j].Price == price) newPets[j] = null;
}
}
As D Stanley has noticed (but I've missed it) you may have to set Price to null instead of whole record. Then simply change it to decimal? and then write newPets[i].Price = null; instead of null`ing whole record.
Well for starters a decimal can't be null, so I'll answer it as if you had a decimal? type so you understand the process.
Linq is for querying, not updating. You could project a new collection based on the original, but a foreach may be more appropriate:
// list to keep tack of found prices
var prices = new List<decimal>();
foreach(Pet pet in pets)
{
if(prices.Contains(pet.Price.Value))
// price was found - set this one to null
pet.Price = null;
else
// add to the list of "found" prices
prices.Add(pet.Price.Value);
}
public class Pet
{
public string Name { get; set; }
public string Other { get; set; }
public decimal? Price { get; set; }
}
Note that the Price is now nullable (decimal?)
return pets
.OrderBy(x => x.Name)
.GroupBy(x => x.Price)
.OrderBy(x => x.Key)
.SelectMany(x => (new[] { x.First() }).Union(x.Skip(1).Select(n => new Pet { Name = n.Name, Other = n.Other, Price = null })))
.ToList();

Categories