Viewmodel with conditional aggregation (Sums) - asp.net-mvc

I have a viewmodel
public class RecTotal
{
public string PayType { get; set; }
public decimal TotalPrice { get; set; }
public string Category { get; set; }
}
public class ReconcileViewModel
{
public IEnumerable<RecTotal> RecTotals { get; set; }
public IEnumerable<RecInvoiceLineItem> LineItems { get; set; }
}
How do I create sums of the categories and create a new RecTotal record for each one. Ex:
ReconcileViewModel VM = new ReconcileViewModel();
foreach(POSItemCategory cat in db.POSItemCategories)
{
recLineItems.Where(p => p.Category == cat.ID).Sum(p => p.InvPrice);
}
The end result i'm looking for is something like
VM.RecTotal.Add(Sum(TotalPrice), foreach(Category)
I know I'm close but I just cant quite get it.

I found a way to do this, but it is "Ugly" in my opinion and there has to be a better way to do it....
var test = new List<RecTotal>();
foreach (POSItemCategory cat in db.POSItemCategories)
{
test.Add(new RecTotal
{
NumberOfItems = recLineItems.Where(p => p.Category == cat.ID).Count(),
TotalPrice = recLineItems.Where(p => p.Category == cat.ID).Sum(p => p.InvPrice),
PayType = "All",
Category = cat.Name,
NumberOfInvoices = recLineItems.Where(p => p.Category == cat.ID).Select(p => p.InvID).Distinct().Count()
});
};
VM.RecTotals = test;
Please let me know if there is a better way of doing this.

you can try this
var testdata = new List<RecTotal>();
testdata = recLineItems.Where(x => db.POSItemCategories.Select(a=>a.ID).Contains(x.Category))
.GroupBy(x => x.Category)
.Select(
x =>
new RecTotal()
{
Category = x.Key,
PayType = "All",
TotalPrice = x.Sum(z => z.InvPrice),
NumberOfItems = x.Count(),
NumberOfInvoices = x.Select(p => p.InvID).Distinct().Count()
}).ToList();

Related

Retrieving Children from Multiple Parent Types, and Associating Them

What is the most efficient way to
a) retrieve all children objects from multiple parent types, and
b) know what the parent type is and the exact parent Id for each child?
Currently this is what I'm doing and it's incredibly inefficient, at least the part where I find the specific parent of each child.
public class ChildModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ParentType1Model
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ChildModel> Children { get; set; }
}
public class ParentType2Model
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ChildModel> Children { get; set; }
}
//Get all ChildModels from ParentType1
var parentType1Children = db.ParentType1Models
.SelectMany(x => x.Children)
.ToList();
listOfChildModels.AddRange(parentType1Children);
//Get all ChildModels from ParentType2
var parentType2Children = db.ParentType2Models
.SelectMany(x => x.Children)
.ToList();
listOfChildModels.AddRange(parentType2Children);
//Find the parent for each ChildModel
foreach (var child in listOfChildModels)
{
ParentType1Model parentType1ModelCheck = null;
ParentType2Model parentType2ModelCheck = null;
parentType1ModelCheck = await db.ParentType1Models
.Where(p => p.Children
.Any(i => i.Id == child.Id))
.FirstOrDefaultAsync();
//If first check is null, then move to second check
if (taskProjectModelCheck == null)
{
parentType2ModelCheck = await db.ParentType2Models
.Where(p => p.Children
.Any(i => i.Id == child.Id))
.FirstOrDefaultAsync();
}
//Now record the parent type and parent Id in an object containing the original ChildModel and it's parent's info (to be used later for various things)
ChildViewModel childViewModel = new ChildViewModel();
childViewModel.ChildModel = child;
if (parentType1ModelCheck != null)
{
childViewModel.ParentType = "ParentType1";
childViewModel.ParentModelId = parentType1ModelCheck.Id;
}
else if (parentType2ModelCheck != null)
{
childViewModel.ParentType = "ParentType2";
childViewModel.ParentModelId = parentType2ModelCheck.Id;
}
}
How about something like this?
var ids1 = from p in db.ParentType1Models
from c in p.Children
select new
{
parentId = p.Id,
parentName = p.Name,
childName = c.Name,
childId = c.Id,
ParentType = "One"
};
var ids2 = from p in db.ParentType2Models
from c in p.Children
select new
{
parentId = p.Id,
parentName = p.Name,
childName = c.Name,
childId = c.Id,
ParentType = "Two"
};
var results = ids1.Union(ids2).ToList();
I ended up using raw SQL, and it is extremely fast.
By writing a query directly against the database, I was able to go straight to the many to many relationship tables that get created by Entity Framework when I set up the ParentTypeXModels and ChildModels.
result = dbContext.Database.SqlQuery<ANewChildObject>(
"select
ParentModelId = pm.Id,
Id = c.Id,
ParentType = 'ParentType1'
from dbo.ChildModels c
JOIN dbo.ParentType1ModelsChildModels pmT ON c.Id = pmT.ChildModel_Id
JOIN dbo.ParentType1Models pm on pmT.ParentType1Model_Id = pm.Id
UNION ALL
select
ParentModelId = pm.Id,
Id = c.Id,
ParentType = 'ParentType2'
from dbo.ChildModels c
JOIN dbo.ParentType2ModelsChildModels pmT ON c.Id = pmT.ChildModel_Id
JOIN dbo.ParentType2Models pm on pmT.ParentType2Model_Id = pm.Id"
).ToList();

.Join .Group Lambda multiple table

I need to convert:
SELECT Author.AuthorName, Author.AuthorSurname , Category.CategoryName, COUNT(Record.IdCategory) AS Ilosc
FROM ((Record
INNER JOIN Author ON Author.Id = Record.IdAuthor)
INNER JOIN Category ON Category.Id = Record.IdCategory)
GROUP BY AuthorName, AuthorSurname, CategoryName
Order by Ilosc ASC
To lambda.
I have created
public class SortModel
{
public string Imie { get; set; }
public string Nazwisko { get; set; }
public string Kategoria { get; set; }
}
For now i wrote this code but i need to add .groupby:
public List<SortModel> GetAuthorCategories()
{
var context = new KolekcjaPlytEntities2();
List<SortModel> queryAllCustomers = context.Record
.Join( context.Author, r => r.IdAuthor, a => a.Id, (r, a) => new {r, a})
.Join(context.Category, c => c.r.IdCategory, cn => cn.Id, (c, cn) => new SortModel()
{
Imie = c.a.AuthorName,
Nazwisko = c.a.AuthorSurname,
Kategoria = cn.CategoryName,
})
.ToList();
return queryAllCustomers;
}
Thanks.
You could use LINQ query expression like this one.
List<SortModel> queryAllCustomers = (from r in context.Record
join a in context.Author on r.IdAuthor equals a.Id
join c in context.Category on r.IdCategory equals c.Id
group new {a, c} by new {a.AuthorName, a.AuthorSurname , c.CategoryName} into gruopAC
let countCategory= gruopAC.Count()
orderby countCategory
select new SortModel
{
Imie=gruopAC.Key.AuthorName,
Nazwisko =gruopAC.Key.AuthorSurname ,
Kategoria =gruopAC.Key.CategoryName,
Ilosc=countCategory}).ToList()
Suppose you have
public class SortModel
{
public string Imie { get; set; }
public string Nazwisko { get; set; }
public string Kategoria { get; set; }
public int Ilosc { get; set; }
}
You can try this code:
public List<SortModel> GetAuthorCategories()
{
var context = new KolekcjaPlytEntities2();
List<SortModel> queryAllCustomers = context.Record
.Join(context.Author, r => r.IdAuthor, a => a.Id, (r, a) => new {r, a})
.Join(context.Category, ar => ar.r.IdCategory, c => c.Id, (ar, c) => new {
r = ar.r,
a = ar.a,
c = c
})
// Here you have a IEnumerable<dynamic> of items { a = Author, c = Category, r = Record }
// All items with same { a.Id, c.Id } are grouped
.GroupBy(x => new { x.a.Id, x.c.Id }, (x, items) => new SortModel()
{
// First() cannot return null, we have inner join everywhere
Imie = items.First().a.AuthorName,
Nazwisko = items.First().a.AuthorSurname,
Kategoria = items.First().c.CategoryName,
Ilosc = items.Count()
})
.ToList();
return queryAllCustomers;
}

Json Data from datatable

Here i have a problem with data table to convert json. This is my class called SearchCollection
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public int ClassGroupId { get; set; }
public string ClassName { get; set; }
public int ClassNumber { get; set; }
public int BookTypeId { get; set; }
public string BookType { get; set; }
I have collected a data from store procedure and pushed into the datatable, thats why am using ConvertToDatatable(), that time i got a datatable which contains 3 tables data
static DataTable ConvertToDatatable(IEnumerable<SearchCollection> list)
{
var dt = new DataTable();
dt.Columns.Add("CategoryId");
dt.Columns.Add("CategoryName");
dt.Columns.Add("ClassGroupId");
dt.Columns.Add("ClassName");
dt.Columns.Add("ClassNumber");
dt.Columns.Add("BookTypeId");
dt.Columns.Add("BookType");
foreach (var item in list)
{
var row = dt.NewRow();
row["CategoryId"] = item.CategoryId;
row["CategoryName"] = item.CategoryName;
row["ClassGroupId"] = item.ClassGroupId;
row["ClassName"] = item.ClassName;
row["ClassNumber"] = item.ClassNumber;
row["BookTypeId"] = item.BookTypeId;
row["BookType"] = item.BookType;
dt.Rows.Add(row);
}
return dt;
}
this contain 3 tables data.
So.. this is have tried to group the data, but here am getting the answer like category on top inside category shows booktype and inside booktype shows list of classnames, but i want 3 set of data
category {},booktype{},classnames{}
var result = rows.GroupBy(r => new { x = r["CategoryId"], y = r["CategoryName"] }).Select(g => new
{
CategoryId = g.Key.x,
CategoryName = g.Key.y,
BookTypes = g.GroupBy(r => new { h = r["BookTypeId"], i = r["BookType"] }).Select(g1 => new
{
BookTypeId = g1.Key.h,
BookType = g1.Key.i,
ClassNames = g1.Select(r => new
{
ClassGroupId = r["ClassGroupId"],
ClassName = r["ClassName"],
ClassNumber = r["ClassNumber"]
}),
}),
});
Rusult
This is my result
{ CategoryId:1 CategoryName:CD ClassGroupId:15 ClassName:I ClassNumber:1 BookTypeId:1 BookType:General CD}
{ CategoryId:2 CategoryName:DVD ClassGroupId:16 ClassName:II ClassNumber:2 BookTypeId:2 BookType:General DVD}
{ CategoryId:3 CategoryName:Book ClassGroupId:17 ClassName:III ClassNumber:3 BookTypeId:3 BookType:General Books}
But i want the result like this
+ Category={ CategoryId:1 CategoryName:CD
CategoryId:2 CategoryName:DVD
CategoryId:3 CategoryName:Book }
ClassGroup={ClassGroupId:15 ClassName:I ClassNumber:1
ClassGroupId:16 ClassName:II ClassNumber:2
ClassGroupId:17 ClassName:III ClassNumber:3}
BookType{ BookTypeId:1 BookType:General CD
BookTypeId:2 BookType:General DVD
BookTypeId:3 BookType:General Books
}
here my result is booktype is under category and classname under booktype. but i want the result just like 3 groups of records in single json, any one help just like category grouped collection, class grouped collection and book type collection in single json data.
Is this what you're looking for?
var result = new
{
Category = rows
.GroupBy(r => new
{
x = r["CategoryId"],
y = r["CategoryName"]
})
.Select(g => new
{
CategoryId = g.Key.x,
CategoryName = g.Key.y
}),
ClassGroup = rows
.GroupBy(r => new
{
x = r["ClassGroupId"],
y = r["ClassName"],
z = r["ClassNumber"]
})
.Select(g => new
{
ClassGroupId = g.Key.x,
ClassName = g.Key.y,
ClassNumber = g.Key.z
}),
BookType = rows
.GroupBy(r => new
{
x = r["BookTypeId"],
y = r["BookType"]
})
.Select(g => new
{
BookTypeId = g.Key.x,
BookType = g.Key.y
})
};
Fiddle: https://dotnetfiddle.net/h9qXqc

Kendo treeview expander not coming

i am creating one Kendo treeview as written below
#(Html.Kendo().TreeView()
.Name("treeview")
.Template("<a class='edit-link' onclick=javascript:EditNode(#= item.id #) href='\\#'>#= item.text #</a> <a class='add-link' onclick=javascript:AddNode(#= item.id #) href='\\#'>Add</a>")
.HtmlAttributes(new { #class = "demo-section" })
.DataSource(source =>
{
source.Read(read => read.Action("Read_TemplateData", "Role"));
})
)
and in the controller action i am returning like
public ActionResult Read_TemplateData(string id)
{
IEnumerable<KendoTreeviewModel> result;
var AllPrivileges = ContextService.GetAllPrivilege(Evry.Ecompanion.Web.Common.SessionManager.AuthorizedInfo.UserId);
if (string.IsNullOrEmpty(id))
{
result = AllPrivileges.Where(p => p.Id == p.ParentPrivilegeId).Select(p => new KendoTreeviewModel { text = p.Name, id = p.Id,expanded=false, items = GetChilderns(p.Id) }).ToList();
}
else
{
result = AllPrivileges.Where(p => p.ParentPrivilegeId == Convert.ToInt32(id, CultureInfo.InvariantCulture) && p.Id != Convert.ToInt32(id, CultureInfo.InvariantCulture)).Select(p => new KendoTreeviewModel { text = p.Name, id = p.Id}).ToList();
}
return Json(result, JsonRequestBehavior.AllowGet);
}
public List<KendoTreeviewModel> GetChilderns(int id)
{
var AllPrivileges = ContextService.GetAllPrivilege(Evry.Ecompanion.Web.Common.SessionManager.AuthorizedInfo.UserId);
return AllPrivileges.Where(p => p.ParentPrivilegeId == Convert.ToInt32(id, CultureInfo.InvariantCulture) && p.Id != Convert.ToInt32(id, CultureInfo.InvariantCulture)).Select(p => new KendoTreeviewModel { text = p.Name, id = p.Id }).ToList();
}
and the viewmodel is like
public class KendoTreeviewModel
{
[DataMember]
public int id { get; set; }
[DataMember]
public string text { get; set; }
[DataMember]
public bool expanded { get; set; }
[DataMember]
public List<KendoTreeviewModel> items { get; set; }
}
in the result the Parent and child lists are coming, but the expander in the treeview is not coming
the output is coming without treeview expander, only parent nodes are displaying.
please anybody help me in resolving the issue.
Thanks in advance,
Rudresh
you are not passing Id to your controller
source.Read(read => read.Action("Read_TemplateData", "Role", new{id=#= item.id #}));
You need hasChildren property in order to get the child records
in KendoTreeviewModel class add this property hasChildren then
change
result = AllPrivileges.Where(p => p.Id == p.ParentPrivilegeId).Select(p => new KendoTreeviewModel { text = p.Name, id = p.Id,expanded=false, items = GetChilderns(p.Id) }).ToList();
to
result = AllPrivileges.Where(p => p.Id == p.ParentPrivilegeId).Select(p => new KendoTreeviewModel { text = p.Name, id = p.Id,expanded=false, items = GetChilderns(p.Id),
hasChildren = GetChilderns(p.Id).count() > 0}).ToList();

Only parameterless constructors and initializers are supported in LINQ to Entities

There are several same questions that have same problem. But I cant find solution for me.
LinQ
var result = (from a in entity.TblAnalizorReadings
group a by new { date = new DateTime(((DateTime)a.okuma_tarihi).Year, ((DateTime)a.okuma_tarihi).Month, ((DateTime)a.okuma_tarihi).Day, ((DateTime)a.okuma_tarihi).Hour, 0, 0) } into g
select new AnalizorPivotChartModel
{
okuma_tarihi = g.Key.date,
Gerilim_Faz1 = g.Max(x => x.Gerilim_Faz1),
Gerilim_Faz2 = g.Max(x => x.Gerilim_Faz2),
Gerilim_Faz3 = g.Max(x => x.Gerilim_Faz3)
}).ToList();
Model
public class AnalizorPivotChartModel
{
public Nullable<System.DateTime> okuma_tarihi { get; set; }
public Nullable<decimal> Gerilim_Faz1 { get; set; }
public Nullable<decimal> Gerilim_Faz2 { get; set; }
public Nullable<decimal> Gerilim_Faz3 { get; set; }
}
I get error message as this question title. I can write more code if its neccesary.
Thanks.
var result = entity.TblAnalizorReadings
.GroupBy(a =>
new {
((DateTime)a.okuma_tarihi).Year,
((DateTime)a.okuma_tarihi).Month,
((DateTime)a.okuma_tarihi).Day,
((DateTime)a.okuma_tarihi).Hour
},
(k, g) => new {
okuma_tarihi = k,
Gerilim_Faz1 = g.Max(x => x.Gerilim_Faz1),
Gerilim_Faz2 = g.Max(x => x.Gerilim_Faz2),
Gerilim_Faz3 = g.Max(x => x.Gerilim_Faz3)
})
.AsEnumerable()
.Select(g => new AnalizorPivotChartModel
{
okuma_tarihi = new DateTime(okuma_tarihi.Year, okuma_tarihi.Month, okuma_tarihi.Day, okuma_tarihi.Hour, 0, 0),
Gerilim_Faz1 = g.Gerilim_Faz1,
Gerilim_Faz2 = g.Gerilim_Faz2,
Gerilim_Faz3 = g.Gerilim_Faz3
})
.ToList();

Resources