Populate list of object using group by in LINQ - c#

I've the following classes
public class R
{
public Guid Id { get; set; }
public string Title { get; set; }
public int RNumber { get; set; }
public int VNumber { get; set; }
}
public class RD
{
public Guid RDId { get; set; }
}
public class RRDS
{
public R R { get; set; }
public string ProjectTitle { get; set; }
public List<RD> RDs{ get; set; }
}
public class RRSDto
{
public Guid Id { get; set; }
public string Title { get; set; }
public string ProjectTitle { get; set; }
public int RNumber { get; set; }
public int VNumber { get; set; }
public Guid RDId { get; set; }
}
From the database i get the list of RRSDto. i need to convert the list of RRSDto to list of RRDS. The Id, Title, ProjectTile, RNumber, VNumber can be same but the RDId will be different.
This is what i've tried with LINQ:
var temp = (from r in rrs
group r by new
{
r.Id,
r.Title,
r.ProjectTitle,
r.RNumber,
r.VNumber,
} into gcs
select new RRDS()
{
R = new R()
{
Id = gcs.Key.Id,
Title = gcs.Key.Title,
RNumber = gcs.Key.RNumber,
VNumber = gcs.Key.VNumber
},
ProjectTitle = gcs.Key.ProjectTitle,
RDs = new List<RD>()
{
new RD()
{
RDId = gcs.ToList().Select(g => g.RDId).FirstOrDefault()
}
}
}).ToList();
Instead of FirstOrDefault i want the list of RDIds. How do i get it using LINQ?
Thanks in advance,
Suyog

If you want all the RDId then simply project them using Select, I don't see any reason to use FirstOrDefault since you are not looking for first RDId within the group:-
,RDs = gcs.Select(g => new RD { RDId = g.RDId }).ToList()

Related

How to get icollection data sending from web api to My object class?

i am receiving the data from web api but dont know how to Get this Icollection stuff to my Model object
Api Controller
public IHttpActionResult Campaigndetails(int id)
{
IList<CampaignViewModel> list = null;
using (IdonateEntities2 entities = new IdonateEntities2())
{
list = entities.Campaigns.Include(x => x.Donors).Select(x =>
new CampaignViewModel()
{
campaign_id = x.campaign_id,
title = x.title,
description = x.description,
amount = x.amount,
image = x.image,
raised_amount = x.raised_amount,
category_id = x.category_id,
user_id = x.user_id,
Donor = x.Donors.Select(d=> new DonorViewModel()
{
donor_id = d.donor_id,
donor_name = d.donor_name,
donated_amount = d.donated_amount,
campaign_id = d.campaign_id,
payment_id = d.payment_id
}).ToList()
}).ToList().Where(x => x.campaign_id == id).ToList();
return Ok(list);
}
Campaign Controller:
public ActionResult Detail(int id)
{
List<Category> category = new List<Category>();
string text = string.Empty;
var request = WebRequest.Create("http://localhost:49210/api/campaign/campaigndetails/"+ id);
var response = (HttpWebResponse)request.GetResponse();
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
category = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<List<Category>>(text);
}
return View(category);
}
My Model Classes:
public class Category
{
public Category()
{
this.Donors = new HashSet<DonorViewModel>();
}
public int campaign_id { get; set; }
public string title { get; set; }
public string description { get; set; }
public int amount { get; set; }
public int zipcode { get; set; }
public int category_id { get; set; }
public int user_id { get; set; }
public Nullable <int> raised_amount { get; set; }
public string image { get; set; }
public virtual ICollection<DonorViewModel> Donors { get; set; }
}
public class DonorViewModel
{
public int donor_id { get; set; }
public string donor_name { get; set; }
public int donated_amount { get; set; }
public int campaign_id { get; set; }
public int payment_id { get; set; }
public Nullable<int> user_id { get; set; }
public virtual Category Category { get; set; }
}
}
text is showing all data received by web api but category object showing no data in Donor i want to receive it and passed to my view to show

From the tree structure get list

I have a class CategoryModel in c#, which is an element of a tree:
public class CategoryModel
{
public string Id { get; set; }
public string Name { get; set; }
public string NameEng { get; set; }
public string ParentCategoryId { get; set; }
public ICollection<string> ChildCategoriesIds { get; set; } = new List<string>();
public ICollection<string> ProductsIds { get; set; } = new List<string>();
}
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public string NameEng { get; set; }
}
The ChildCategoriesIds contains Id class CategoryModel.
The ProductsIds contains Id class Product.
How proccesed data in new classes:
public class CategoryNew
{
public string Uid { get; set; }
public string Name { get; set; }
public string NameEng { get; set; }
public bool? IsDeleted { get; set; }
public IEnumerable<UidName> ChildCategories { get; set; } = new List<UidName>();
public IEnumerable<UidName> Products { get; set; } = new List<UidName>();
}
public class UidName
{
public string Uid { get; set; }
public string Name { get; set; }
public string NameEng { get; set; }
public bool? IsDeleted { get; set; }
}
You can specify own constructor for CategoryNew, which will take as an argument object of class CategoryModel, in which you will set all properties of CategoryNew based on values of properties of CategoryModel:
public CategoryNew(CategoryModel cm){
// set properties
}
Then your method would be:
public List<CategoryNew> ConverModelToNew(List<CategoryModel> lstCatModel){
List<CategoryNew> lstCatNew = new List<CategoryNew>();
foreach(var item in lstCatModel){
lstCatNew.Add(new CetagoryNew(item));
}
return lstCatNew;
}
Assuming you are trying to convert one set of object to another set of objects.
First of all, I believe categories shouldl inherit UidName so you will memory more efficiently by reducing duplicate objects.
public class CategoryNew: UidName
{
public IEnumerable<CategoryNew> ChildCategories { get; set; } = new List<CategoryNew>();
public IEnumerable<UidName> Products { get; set; } = new List<UidName>();
}
public class UidName
{
public string Uid { get; set; }
public string Name { get; set; }
public string NameEng { get; set; }
public bool? IsDeleted { get; set; }
}
// first run to create products
var newProducts = products.Select(p => new UidName {
Uid = p.Id,
Name = p.Name,
NameEnd = p.NameEng
}).ToArray();
// second run to create categories with products
var newCategories = categories.Select(c => new CategoryNew {
Uid = c.Id,
Name = c.Name,
NameEng = c.NameEng,
IsDeleted = (bool?)null, //TODO
Products = newProducts.Where(p => c.ProductIds.Contains(p.Uid))
.ToList()
}).ToArray();
// last run find sub categories
foreach(var category in newCategories) {
var oldCategory = categories.First(c => c.Id == category.Uid);
category.ChildCategories = newCategories.Where(c => oldCategory.ChildCategoriesIds.Contains(c.Uid))
.ToArray();
}

Way to create composite objects from a single (flat) database query

I am getting product data from our ERP through SQL queries whereby the returned data is very flat- at the Size level. A product has 3 levels:
Style
Colours
Sizes
A style has many colours and a colour has many sizes.
I have created the following models:
public class Ap21Style
{
public int StyleIdx;
public string StyleCode;
public IList<Ap21Clr> Clrs { get; set; } = new List<Ap21Clr>();
}
public class Ap21Clr
{
public int ClrIdx { get; set; }
public string ColourCode { get; set; }
public string ColourName { get; set; }
public string ColourTypeCode { get; set; }
public string ColourTypeName { get; set; }
public IList<Ap21Sku> Skus { get; set; } = new List<Ap21Sku>();
}
public class Ap21Sku
{
public int SkuIdx { get; set; }
public string SizeCode { get; set; }
public int SizeSequence { get; set; }
public string Barcode { get; set; }
}
My ProductResult looks like this:
public int StyleIdx { get; set; }
public int ClrIdx { get; set; }
public int SkuIdx { get; set; }
public string StyleCode { get; set; }
public string ColourCode { get; set; }
public string ColourName { get; set; }
public string SizeCode { get; set; }
public int SizeSequence { get; set; }
public string ColourTypeCode { get; set; }
public string ColourTypeName { get; set; }
public string Barcode { get; set; }
public string WebData { get; set; }
What would be an effective way to loop over the results and create the Ap21Style models whereby they are a composite object with Ap21Clr's, then at the row level, the Colours have Ap21Sku's?
Assuming something like this
List<ProductResult> products = GetPropducts();
Composing the styles would involve grouping the data by the composite keys
List<Ap21Style> results = products
.GroupBy(p => new { p.StyleIdx, p.StyleCode })
.Select(g => new Ap21Style {
StyleIdx = g.Key.StyleIdx,
StyleCode = g.Key.StyleCode,
Clrs = g.GroupBy(s => new {
s.ClrIdx,
s.ColourCode,
s.ColourName,
s.ColourTypeCode,
s.ColourTypeName
}).Select(g1 => new Ap21Clr {
ClrIdx = g1.Key.ClrIdx,
ColourCode = g1.Key.ColourCode,
ColourName = g1.Key.ColourName,
ColourTypeCode = g1.Key.ColourTypeCode,
ColourTypeName = g1.Key.ColourTypeName,
Skus = g1.Select(s => new Ap21Sku {
Barcode = s.Barcode,
SizeCode = s.SizeCode,
SizeSequence = s.SizeSequence,
SkuIdx = s.SkuIdx
}).ToList()
}).ToList()
}).ToList();

How to store specific data into list with class

i want ask about storing data into list but not all data like this,
class Category :
public class CategoryEnt
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public int ParentID { get; set; }
public bool IsDisplayed { get; set; }
public bool IsTopCat { get; set; }
public bool IsTrending { get; set; }
public int SequenceID { get; set; }
public string Filtering { get; set; }
public string ImageURL { get; set; }
}
i just want add to list CategoryID, CategoryName, ImageUrl
while (reader.Read())
{
CategoryEnt category = new CategoryEnt();
category.CategoryID = Convert.ToInt32(reader["CategoryID"]);
category.CategoryName = reader["CategoryName"].ToString();
category.ImageURL = reader["ImageURL"].ToString();
list.Add(category);
}
the right now, rest of data include but with default/null value, i dont want rest of data include to list. how to store just specific data to list? any clue?
You cannot do that Directly, but indirectly you can achieve the same by using the following code:
List<CategoryEnt> CategoryEntList = new List<CategoryEnt>();
while (reader.Read())
{
CategoryEntList.Add(new CategoryEnt(){
CategoryID = Convert.ToInt32(reader["CategoryID"]),
CategoryName = reader["CategoryName"].ToString(),
ImageURL = reader["ImageURL"].ToString(),
});
}
var requiredValues = CategoryEntList.Select(x => new
{ CategoryID = x.CategoryID,
CategoryName = x.CategoryName,
ImageURL = x.ImageURL
}).ToList();
Now requiredValues is a List that will contains only those value that you ware specified in the Select You can proceed with that;
Try a class with just the information you require. Something like:
public class Category
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public string ImageURL { get; set; }
}
Then you can create your original class using
public class CategoryEnt
{
public Category CategoryPrimaryDetails { get; set; }
public int ParentID { get; set; }
public bool IsDisplayed { get; set; }
public bool IsTopCat { get; set; }
public bool IsTrending { get; set; }
public int SequenceID { get; set; }
public string Filtering { get; set; }
}
And your original code becomes:
List<Category> list = new List<Category>();
while (reader.Read())
{
Category category = new Category() {
CategoryID = Convert.ToInt32(reader["CategoryID"]);
CategoryName = reader["CategoryName"].ToString();
ImageURL = reader["ImageURL"].ToString()
}
list.Add(category);
CategoryEnt detailedCategory = new CategoryEnt() {CategoryPrimaryDetails = category};
}

How to partition a query and load only a few properties with Linq to Entities?

I have the following POCOs:
public Ticket
{
public int Id { get; set; }
public int IdOwner { get; set; }
public int IdDependency { get; set; }
public string SerialNumber { get; set; }
public Owner Owner { get; set; }
public Dependency Dependency { get; set; }
}
public Owner
{
public int Id { get; set; }
public string Name { get; set; }
// Other attributes
}
public Dependency
{
public int Id { get; set; }
public string Name { get; set; }
// Other attributes
}
I want to return a List of Tickets that has only Owner Name and Dependency Name. The problem is, i will write a where with Owner if in my filter i pass the OwnerId, and the same to Dependency. Look to my filter:
public List<Ticket> SelectTickets(string SerialNumber, int IdOwner, int IdDependency)
{
IQueryble<Ticket> query = context.Tickets.Where(t => t.SerialNumber == SerialNumber);
if (IdOwner != 0)
{
query = query.Where( ?? );
}
if (IdDependency!= 0)
{
query = query.Where( ?? );
}
return query.ToList();
}
That would make sense, if i understood what you mean.
public Ticket
{
public int Id { get; set; }
public int OwnerId{ get; set; }
public int DependencyId { get; set; }
public string SerialNumber { get; set; }
public Owner Owner { get; set; }
public Dependency Dependency { get; set; }
}
public Owner
{
public int Id { get; set; }
public string Name { get; set; }
public List<Ticket> Tickets {get;set;}
}
public Dependency
{
public int Id { get; set; }
public string Name { get; set; }
public List<Ticket> Tickets {get;set;}
}
public List<Ticket> SelectTickets(string serialNumber, int ownerId, int dependencyId)
{
return context.Tickets.Where(t => t.SerialNumber == serialNumber && t.OwnerId == ownerId && t.DependencyId == dependencyId).ToList();
}
You could project your resulting query to any format you like AFTER filtering it.
Does replacing the return statement with this work for you or do you have more complex requirements I did not fully understand?
return query.Select(t => new Ticket() {
Owner = t.Owner,
Dependency = t.Dependency;
}.ToList();
Use the select statement.
query = query.Select(t => new Ticket {
Owner = new Owner {Name = t.Owner.Name},
Dependency = new Dependency {Name = t.Dependency.Name}
});
return query.ToList();
However, it seems that in this case you would not want to return a Ticket but some other object such as TicketSummary
public class TicketSummary {
public OwnerName {get;set;}
public DependencyName {get;set;}
}
Then you would have
query = query.Select(t => new TicketSummary {
OwnerName = t.Owner.Name,
DependencyName = t.Dependency.Name
});
return query.ToList();

Categories

Resources