I have a list of product class, e.g:
{
Name = "Product 1",
Category = "TV",
Region = "China"
},
{
Name = "Product 2",
Category = "Watch",
Region = "Germany"
},
{
Name = "Product 3",
Category = "Smartphone",
Region = "USA"
}
and unsorted product price list for every year (in format product, year and amount), e.g:
Product 1, 2016, $2000
Product 2, 2016, $300
Product 1, 2017, $1800
Product 3, 2017, $500
Product 2, 2017, $290
I need to display the products with price - to show the comparison of price for every year. The end result should look like this:
Name Category Year 2016 Year 2017
Product 1 TV 2000 1800
Product 2 Watch 300 290
Product 3 Smartphone - 500
Since the price list will expand every year, therefore I plan to keep a list of string as properties in class.
List<string> Headers = new List<string> {
"Name",
"Category",
"Region"
};
foreach (string year in distinctYear)
{
Headers.Add("Y" + year);
}
Until here, I'm stuck, how can I convert them into a class, so that I could assign the value like this:
{
Name = "Product 1",
Category = "TV",
Y2016 = 2000,
Y2017 = 1800
},
{
Name = "Product 2",
Category = "Watch",
Region = "Germany",
Y2016 = 300,
Y2017 = 290
},
{
Name = "Product 3",
Category = "Smartphone",
Region = "USA",
Y2017 = 500
}
Any help or suggestion is much appreciated.
Use a dictionary where the key is the year and the value is the price.
class Product
{
public string Name { get; set; }
public string Category { get; set; }
public string Region { get; set; }
public IDictionary<int, decimal> PricePerYear { get; set; }
= new Dictionary<int, decimal>( );
}
var prod = new Product
{
Name = "Product1",
Category = "TV",
Region = "China",
};
prod.PricePerYear.Add( 2016, 2000 );
prod.PricePerYear.Add( 2017, 4500 );
OR (C#7)
Lets use some Tuples! As per Chris's comment you can also initialize the list/dictionary during creation.
class Product
{
public string Name { get; set; }
public string Category { get; set; }
public string Region { get; set; }
public IList<(int year, decimal amount)> PricePerYear { get; set; }
}
var prod = new Product
{
Name = "Product1",
Category = "TV",
Region = "China",
PricePerYear = new List<(int year, decimal amount)>
{
(year: 2016, amount: 5000),
(2017, 10000),
(2018, 5000),
}
};
(int year, decimal price) = prod.PricePerYear.First( );
Console.WriteLine( $"Year: {year} Price: {price}" );
Console.ReadLine( );
You could use a list to store the prices; for example using these two classes:
class Product
{
public string Name { get; set; }
public string Category { get; set; }
public string Region { get; set; }
public List<Price> Prices { get; set; }
}
class Price
{
public int Year { get; set; }
public decimal Amount { get; set; }
}
Then you can initialize an instance of Product as follows:
Product prod1 = new Product()
{
Name = "Product1",
Category = "TV",
Region = "China",
Prices = new List<Price>()
{
new Price()
{
Year = 2016,
Amount = 2000
},
new Price()
{
Year = 2017,
Amount = 1800
}
}
};
I combine both ProductList and PriceList classes into a dictionary:
foreach (var item in ProductList)
{
var dict = new Dictionary<string, object>();
dict["Name"] = item.Name;
dict["Category"] = item.Category;
dict["Region"] = item.Region;
foreach (var i in item.PriceList)
{
dict[i.Year] = i.Amount;
}
list.Add(dict);
}
Related
Sorry for my bad English.
Here is my SQL Design.
I have 3 table in Sqlsever. Each table has 4 column with same name, same datatype.
And i want to get data from 4 column "Id, Name, Quantity, IdCategory" from 3 table into 1 list object same as returning value in this code below:
public async Task<IEnumerable<Shirt>> LoadAllShirt()
{
return await _dbContext.Shirt.ToListAsync();
}
I use .NET Core 6 Mvc - code first. Thanks for your help.
I have 3 table in Sqlsever. Each table has 4 column with same name,
same datatype. And I want to get data from 4 column "Id, Name,
Quantity, IdCategory" from 3 table into 1 list, I use .NET Core 6 Mvc - code first.
Well, lot of way around to handle this kind of scenario. Most easy and convenient way I would prefer to use View model or using Linq query.
Lets assume you have below Models:
Models:
public class Bags
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public string Category { get; set; }
}
public class Shirts
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public string Category { get; set; }
}
public class Shoes
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public string Category { get; set; }
}
Seeds In Models:
List<Bags> listBags = new List<Bags>();
listBags.Add(new Bags() { Id = 101, Name = "Bag A", Quantity =10, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 102, Name = "Bag B", Quantity =15, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 103, Name = "Bag C", Quantity =20, Category = "Cat-A"});
List<Shirts> listShirts = new List<Shirts>();
listShirts.Add(new Shirts() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-B" });
List<Shoes> listShoes = new List<Shoes>();
listShoes.Add(new Shoes() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-S" });
Way: 1 using ViewModel:
public class AllViewModel
{
public List<Bags> Bags { get; set; }
public List<Shirts> Shirts { get; set; }
public List<Shoes> Shoes { get; set; }
}
Query Using ViewModel:
var allTableUsingViewModel = new AllViewModel();
allTableUsingViewModel.Bags = listBags;
allTableUsingViewModel.Shirts = listShirts;
allTableUsingViewModel.Shoes = listShoes;
Output Using ViewModel:
Way: 2 using Linq Annonymous Type:
Query Using Linq Annonymous Type:
var AllTableListUsingLinq = from a in listBags
join b in listShirts on a.Id equals b.Id
join c in listShoes on b.Id equals c.Id
select new
{
FromBagsID = a.Id,
FromBagsName = a.Name,
FromBagsQuantity = a.Quantity,
FromBagsCategory = a.Category,
FromShirtsID = b.Id,
FromShirtsName = b.Name,
FromShirtsQuantity = b.Quantity,
FromShirtsCategory = b.Category,
FromShoesID = c.Id,
FromShoesName = c.Name,
FromShoesQuantity = c.Quantity,
FromShoesCategory = c.Category
};
Output Using Linq Annonymous Type:
Full Controller:
[HttpGet("GetFrom3Tables")]
public IActionResult GetFrom3Tables()
{
List<Bags> listBags = new List<Bags>();
listBags.Add(new Bags() { Id = 101, Name = "Bag A", Quantity =10, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 102, Name = "Bag B", Quantity =15, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 103, Name = "Bag C", Quantity =20, Category = "Cat-A"});
List<Shirts> listShirts = new List<Shirts>();
listShirts.Add(new Shirts() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-B" });
List<Shoes> listShoes = new List<Shoes>();
listShoes.Add(new Shoes() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-S" });
//Way: 1 Linq Query
var AllTableListUsingLinq = from a in listBags
join b in listShirts on a.Id equals b.Id
join c in listShoes on b.Id equals c.Id
select new
{
FromBagsID = a.Id,
FromBagsName = a.Name,
FromBagsQuantity = a.Quantity,
FromBagsCategory = a.Category,
FromShirtsID = b.Id,
FromShirtsName = b.Name,
FromShirtsQuantity = b.Quantity,
FromShirtsCategory = b.Category,
FromShoesID = c.Id,
FromShoesName = c.Name,
FromShoesQuantity = c.Quantity,
FromShoesCategory = c.Category
};
//Way: 2 : ViewModel
var allTableUsingViewModel = new AllViewModel();
allTableUsingViewModel.Bags = listBags;
allTableUsingViewModel.Shirts = listShirts;
allTableUsingViewModel.Shoes = listShoes;
return Ok(AllTableListUsingLinq);
}
Note: If you need more information you could check our official document for View Model and Linq Projction here
The following sample query will list your 3 types of data into a single result set.
var allResults = resultSet1.Concat(resultSet2);
For the return type create a class which will be the parent class for all your products (Bag,Shirt,Shoes) Which will help you to return data in a single Generic data.
If you use any non-generic list to send the data like hashtable or Arraylist then then there will be no issue.
In my way I will suggest to use generic data list as it will help you fetch data in better time complexity.
In this case you may need to define additional indirect base class with these 4 parameters. Than you can create Collection of this base class, and concatinate all 3 tables into.
public class BaseEntity
{
public string Name {get;set;}
}
public class Shoes : BaseEntity
{
}
...
public IEnumerable<BaseEntity> GetAllTables()
{
var shirts = await _dbContext.Shirt.ToListAsync();
var shoes = await _dbContext.Shoes.ToListAsync();
var bags = await _dbContext.Bags.ToListAsync();
return shirts.Concat(shoes).Concat(bags);
}
Similar example but witout casting to base class is shown in Enumerable.Concat documentation: https://learn.microsoft.com/pl-pl/dotnet/api/system.linq.enumerable.concat?view=net-7.0
I have a Model called SalesItemModel which has properties such as SaleItemId, SalesID, ProductID, Quantity, and UnitPrice. I pull list from database using SalesItemService.ListSalesItemsDataBySaleID(salesID).
public class SalesItemModel
{
public int SalesItemID { get; set; }
public int SalesID { get; set; }
public int ProductID { get; set; }
public string ProductName { get; set; }
public Nullable<decimal> UnitPrice { get; set; }
public double Quantity { get; set; }
}
Pulling Sales Items:
var salesItem = SalesItemService.ListSalesItemsDataBySaleID(SalesID);
And I want to access quantity and product ID of every row of the returned list to edit data on stock table using those data.
If you just want to access the data in list, you can try the below loop.
foreach(var item in salesItem)
{
item.Quantity = 10;
item.ProductId = 20;
}
var tests = new List<Test>
{
new Test{Name = "Abc", Age = 1},
new Test{Name = "Abc2", Age = 12},
new Test{Name = "Abc3", Age = 13},
new Test{Name = "Abc4", Age = 14},
};
tests = tests.Select(x=>
{
x.Age = 2;
return x;
}).ToList();
Example which you can use.
I would like to make nested list from this one list
public class Product
{
string Id;
string ProductName;
decimal Price;
string Supplier;
int Quantity;
string VersionId;
string TypeId;
}
public class ProductTypeDto
{
public string TypeId { get; set; }
public string ProductName { get; set; }
public string Price { get; set; }
public List<ProductVersionDto> ProductVersions { get; set; }
}
public class ProductVersionDto
{
public string VersionId { get; set; }
public string ProductName { get; set; }
public string Supplier { get; set; }
public int Quantity { get; set; }
}
I would like to know how I can create a list of ProductTypeDto using linq c# .
I need to get all products with the same TypeId , and ProductVersions field should contain products with same version Id (and of course same TypeId).
I don't want to use foreach loops, and I dont want to loop over products twice to make this nested list.. I think there would be a better way using Linq, would be great if you can help..
Edit: I add here what I have done so far, but it is not the way I want this to be fixed.
List<ProductTypeDto> products = this._dbContext
.Products
.Where(product => product.TypeId == query.TypeId)
.Select(product => new ProductTypeDto()
{
TypeId = product.TypeId,
ProductName = product.ProductName,
Price = product.Price,
ProductVersions = product.Products.Where(p => p.TypeId == product.TypeId)
.Select(p => new ProductVersionDto()
{
VersionId = p.VersionId,
ProductName = p.ProductName,
Supplier = p.Supplier,
Quantity = p.Quantity
}).ToList()
})
.ProjectTo<ProductTypeDto>(this._config)
.ToListAsync(cancellationToken);
This is the result I want to get:
var product1 = new Product() { Id = 1, ProductName = "foo", Price = 20, Supplier = "test1", Quantity = 3, VersionId = "1", TypeId = "1" };
var product2 = new Product() { Id = 2, ProductName = "foo1", Price = 60, Supplier = "test2", Quantity = 9, VersionId = "1", TypeId = "1" };
var product3 = new Product() { Id = 3, ProductName = "foo2", Price = 30, Supplier = "test3", Quantity = 5, VersionId = "2", TypeId = "1" };
var product4 = new Product() { Id = 4, ProductName = "foo3", Price = 10, Supplier = "test4", Quantity = 4, VersionId = "1", TypeId = "2" };
var product5 = new Product() { Id = 5, ProductName = "foo4", Price = 50, Supplier = "test5", Quantity = 8, VersionId = "1", TypeId = "3" };
List<ProductVersionDto> p1 = {
new ProductVersionDto { ProductName = "foo", Quantity= 3, Supplier ="test1"}
new ProductVersionDto { ProductName = "foo1", Quantity= 9, Supplier ="test2"}
};
List<ProductVersionDto> p2 = {
new ProductVersionDto { ProductName = "foo3", Quantity= 4, Supplier ="test4"}
};
List<ProductVersionDto> p3 = {
new ProductVersionDto { ProductName = "foo4", Quantity= 8, Supplier ="test5"}
};
List<ProductTypeDto> products = {
new ProductTypeDto{ ProductName = "foo", Price =20, ProductVersions = p1}
new ProductTypeDto{ ProductName = "foo1", Price =60, ProductVersions = p1}
new ProductTypeDto{ ProductName = "foo3", Price =10, ProductVersions = p2}
new ProductTypeDto{ ProductName = "foo4", Price =50, ProductVersions = p3}
}
Try this:
var dtos =
(
from p in products
group new ProductVersionDto()
{
VersionId = p.VersionId,
ProductName = p.ProductName,
Supplier = p.Supplier,
Quantity = p.Quantity
} by new { p.TypeId, p.ProductName, p.Price } into g
select new ProductTypeDto()
{
TypeId = g.Key.TypeId,
ProductName = g.Key.TypeId,
Price = g.Key.Price,
ProductVersions = g.ToList(),
}
).ToList();
It appears that you meant Price to be a decimal in ProductTypeDto, BTW.
Hi I am trying to learn how to create Web ASP.NET applications and I'm stuck on trying to get to this result.
{
"memberNumber":"1234567890",
"forename":"Fred",
"surname":"Smith",
"products":[
{
"name":"Health Ins",
"cost":100
},
{
"name":"Travel Ins",
"cost":150
}
]
}
I cannot figure out how to add different product name/cost for each individual member. I can display the memberNumber/forename/surname but get an error when I add the products.add line to the members.add line.
Here is my member model:
public class Member
{
public int memberNumber { get; set; } = 0;
public string forename { get; set; } = "";
public string surname { get; set; } = "";
public List<Products> products { get; set; }
}
public class Products
{
public string name { get; set; } = "";
public int cost { get; set; } = 0;
}
Here is my controller:
public class MembersController : ApiController
{
List<Member> members = new List<Member>();
List<Products> products = new List<Products>();
public MembersController()
{
members.Add(new Member { memberNumber = 1234567890, forename = "Fred", surname = "Smith"});
members.Add(new Member { memberNumber = 1, forename = "Big", surname = "Ben"});
members.Add(new Member { memberNumber = 2, forename = "Jack", surname = "Ryan" });
products.Add(new Products { name = "Health Ins", cost = 100 });
products.Add(new Products { name = "Travel Ins", cost = 150 });
}
// GET: api/Members
public List<Member> Get()
{
return members;
}
// GET: api/Members/5
public Member Get(int id)
{
return members.Where(x => x.memberNumber == id).FirstOrDefault();
}
}
Did not include the Post/Put/Delete RESTful services.
products.Add(new Products { name = "Health Ins", cost = 100 });
products.Add(new Products { name = "Travel Ins", cost = 150 });
will add those data in
List<Products> products = new List<Products>();
instead of your expectations in Member class.
I think you might want to add products collection in a member instead of another List
You can use Auto-Property Initializers to init products List collection in Member class.
public class Member
{
public int memberNumber { get; set; } = 0;
public string forename { get; set; } = "";
public string surname { get; set; } = "";
public List<Products> products { get; set; } = new List<Products>();
}
the MembersController constructed data will be like this.
public class MembersController : ApiController
{
List<Member> members = new List<Member>();
public MembersController()
{
var member1 = new Member { memberNumber = 1234567890, forename = "Fred", surname = "Smith"};
var member2 = new Member { memberNumber = 1, forename = "Big", surname = "Ben"};
var member3 = new Member { memberNumber = 2, forename = "Jack", surname = "Ryan" };
member1.products.Add(new Products { name = "Health Ins", cost = 100 });
member1.products.Add(new Products { name = "Travel Ins", cost = 150 });
members.Add(member1);
members.Add(member2);
members.Add(member3);
}
// GET: api/Members
public List<Member> Get()
{
return members;
}
// GET: api/Members/5
public Member Get(int id)
{
return members.Where(x => x.memberNumber == id).FirstOrDefault();
}
}
You're pretty much there, but you will need to assign a product list for each member like this:
List<Products> p= new List<Products>();
p.Add(new Products { name = "Health Ins", cost = 100 });
p.Add(new Products { name = "Travel Ins", cost = 150 });
members.Add(new Member { memberNumber = 1234567890, forename = "Fred", surname = "Smith", Products =p});
// Second member
p= new List<Products>();
p.Add(new Products { name = "Big Bens products", cost = 222});
members.Add(new Member { memberNumber = 1, forename = "Big", surname = "Ben", Products =p});
Thus you can add as many members containing as many products you wish. Please note that we're not talking about ArrayLists but about Lists. ArrayLists have been deprecated a long time ago.
In result of linq query I want to get List<Record> records that should contain something like this:
Id=1, Number=1,Weight=23,Street="Testing street"
Id=1, Number=1,Weight=23,Street="Testing street"
Id=1, Number=1,Weight=23,Street="Testing street"
Id=1, Number=1,Weight=23,Street="Testing street"
Id=1, Number=1,Weight=23,Street="Testing street"
Id=1, Number=1,Weight=23,Street="Testing street"
Code:
namespace ConsoleApplication24
{
class Program
{
static void Main(string[] args)
{
List<Train> Depos = new List<Train>();
Train train = new Train();
train.Id = 1;
List<Wagon> wagons = new List<Wagon>();
wagons.Add(new Wagon { Number = 1, Weight = 23 });
wagons.Add(new Wagon { Number = 1, Weight = 23 });
wagons.Add(new Wagon { Number = 1, Weight = 23 });
wagons.Add(new Wagon { Number = 1, Weight = 23 });
wagons.Add(new Wagon { Number = 1, Weight = 23 });
wagons.Add(new Wagon { Number = 1, Weight = 23 });
train.Wagons = wagons;
Depos.Add(train);
List<Adress> Adresses = new List<Adress>();
Adress adress = new Adress();
adress.Id = 1;
adress.Street = "Testing street";
Adresses.Add(adress);
List<Record> records = (from dep in Depos join adr in Adresses on dep.Id equals adr.Id select new Record { Id = dep.Id }).ToList();
}
}
public class Record
{
public int Id { get; set; }
public int Weight { get; set; }
public string Street { get; set; }
public int Number { get; set; }
}
public class Train
{
public int Id { get; set; }
public List<Wagon> Wagons { get; set; }
}
public class Wagon
{
public int Weight { get; set; }
public int Number { get; set; }
}
public class Adress
{
public int Id { get; set; }
public string Street { get; set; }
}
}
What is the best way to do this?
You need to use SelectMany, or, in query syntax, a second from, to flatten your list of lists:
List<Record> records =(from dep in Depos
join adr in Adresses on dep.Id equals adr.Id
from wgn in dep.Wagons
select new Record
{
Id = dep.Id,
Number = wgn.Number,
Weight = wgn.Weight,
Street = adr.Street
}).ToList();
Or less readable LINQ with extension methods :)
IEnumerable<Record> records =
Depos.Join(Adresses,
myTrain => train.Id,
addr => addr.Id,
(myTrain, addr) => myTrain.Wagons
.Select(wagon => new Record
{
Id = addr.Id,
Street = addr.Street,
Number = wagon.Number,
Weight = wagon.Weight
}))
.SelectMany(myWagons => myWagons);
As you see SelectMany method is key method for this query