join 4 tables with linq to ef - c#

I have four tables/classes
public Class Brands
{
public int Id {get;set;}
public string Brand {get;set;}
public String BrandType {get;set;}
}
public Class ManufactureA
{
public int Id {get;set;}
public int BrandsId {get;set;}
public string Product {get;set;}
public int Distributor {get;set;}
}
public Class ManufactureB
{
public int Id {get;set;}
public int BrandsId {get;set;}
public string Product {get;set;}
public int Distributor {get;set;}
}
public Class ManufactureC
{
public int Id {get;set}
public int BrandsId {get;set;}
public string Product {get;set;}
public int Distributor {get;set;}
}
public Class ManufactureD
{
public int Id {get;set;}
public int BrandsId {get;set;}
public string product {get;set;}
public int Distributor {get;set;}
}
I am trying to produce a table that will show the brands and the info from their associated manufactures. For example:
Brand1:
ProductA, DistributorA
Brand2:
ProductB, DistibutorB
Brand3:
ProductC, DistributorC
Brand4:
ProductD, DistributorD
So I started with this code but got confused at the point of deciding how to actually group or project it:
var allBrandsManufactures = from brand in Brands
join factoryA in ManufactureA on factoryA.BrandsId equals brand.Id
join factoryB in ManufactureB on factoryB.BrandsId equals brand.Id
join factoryC in ManufactureC on factoryC.BrandsId equals brand.Id
join factoryD in ManufactureD on factoryD.BrandsId equals brand.Id

First off, if possible, you should really consider redoing your database design. Your design currently has information in the table names. You should be able to combine all the Manufacture tables into one that probably should be called Products. Then there should be an additional column to indicate which manufacturer it is. Like this.
public class Products
{
public int Id {get;set;}
public int BrandsId {get;set;}
public string ProductName {get;set;}
public int Distributor {get;set;}
public string Manufacturer {get;set;}
}
Or you can create a separate Manufacturer table and link the Product table to it via a Foreign Key, but that's only really needed if you have addtional Manufacturer data you want to put in the DB. Then if you get a new Manufacturer you don't have to create a new table. It also makes your query much easier.
Now if you are stuck with this design then you'll want to do unions instead of joins. The best way is to do each Manufacturer query separate and then use Concat to combine them.
var brandA = from brand in Brands
join factoryA in ManufactureA on brand.Id equals factoryA.BrandsId
select new {
Brand = brand.Brand,
Product = factoryA.Product,
Distributor = factoryA.Distributor,
Manufacturer = "A"};
var brandB = from brand in Brands
join factoryB in ManufactureA on brand.Id equals factoryB.BrandsId
select new {
Brand = brand.Brand,
Product = factoryB.Product,
Distributor = factoryB.Distributor,
Manufacturer = "B"};
var brandC = from brand in Brands
join factoryC in ManufactureA on brand.Id equals factoryC.BrandsId
select new {
Brand = brand.Brand,
Product = factoryC.Product,
Distributor = factoryC.Distributor,
Manufacturer = "C"};
var brandD = from brand in Brands
join factoryD in ManufactureA on brand.Id equals factoryD.BrandsId
select new {
Brand = brand.Brand,
Product = factoryD.Product,
Distributor = factoryD.Distributor,
Manufacturer = "D"};
var result = brandA.Concat(brandB).Concat(brandC).Concat(brandD);
You can of course select whatever you want, but you have to select the same thing in each query and use the same names for the Properties.

Related

Loading LINQ results into a ViewModel that has a calculated attribute (column)

I've seen the scenarios where a ViewModel is populated with one LINQ query as shown below. Question: How can I populate the TotalSale attribute (column) - that is a grand total of Sale column - of the following ViewModel? Note: I'm using latest version of ASP.NET Core with VS2015.
ViewModel:
public class CategProdViewModel
{
public string Category { get; set; }
public string ProductName { get; set; }
public float Sale { get; set; }
public float TotalSale { get; set; }
}
Controller:
var innerJoinQuery = from category in categories
join prod in products on category.ID equals prod.CategoryID
select new CategProdViewModel { Category = category.Name, ProductName = prod.Name, Sale = prod.Sale };
You will have many of these in your view:
public class CategProdViewModel
{
public string Category { get; set; }
public string ProductName { get; set; }
public float Sale { get; set; }
public real TotalSale { get; set; }
}
But you will only have the last property TotalSale once. Therefore, change your view model to this:
public class CategProdViewModel
{
public string Category { get; set; }
public string ProductName { get; set; }
public float Sale { get; set; }
}
Create this model for your view and pass it to your view.
public class UseThisOnYourView // Give it another name
{
public List<CategProdViewModel> Items { get; set; }
public real TotalSale { get { return this.Items.Sum(x => x.Sale); } }
}
Then your query will be like this:
var innerJoinQuery = from category in categories
join prod in products on category.ID equals prod.CategoryID
select new CategProdViewModel { Category = category.Name, ProductName = prod.Name, Sale = prod.Sale };
var model = new UseThisOnYourView
{
Items = innerJoinQuery.ToList()
};
NOTE: Please keep in mind you will need to adjust your view to use the new type you are passing to it and adjust the code accordingly.
You don't clarify the structure of Product, but you can Sum multiple values
var innerJoinQuery = from category in categories
join prod in products on category.ID equals prod.CategoryID
select new CategProdViewModel {
Category = category.Name,
ProductName = prod.Name,
Sale = prod.Sale,
TotalSales = products.Sum(t => t.Sale)
};
Without more about the code, it's hard to say, and also, the prod.sale is probably only going to be the amount of the last product. You can use Sum(this IEnumerable<TSource> source, Func<TSource, double> selector) to sum the total of multiple items.
This is a quick answer. It will probably need to be altered depending on what the rest of your code looks like. You can also Group the query results to sum.

How to access many-to-many table via Entity Framework? asp.net

How do I read a many-to-many table via EF? I have no idea how to use the many-to-many table. Let's say Product_Category where it got ProductID and CategoryID.
How can I access it trough e.g.
using(Entities db = new Entities)
{
/* cant access these here.. */}
method?? I can however reach Product_Category, but cant access its ProductID or CategoryID.
I want to list every product e.g. where Product_Category.CategoryID == Category.ID.
I have never used many-to-many tables before, so I appreciate some simple examples how to access them trough EF in asp.net.
Thanks
Navigation properties are your friend here. Unless you have other properties in the junction table, you don't need it. This is why there is no Product_Category in your models. So say your models are:
public class Product
{
public Product()
{
this.Categories = new HashSet<Category>();
}
public int ProductId { get; set; }
public string ProductName { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class Category
{
public Category()
{
this.Products = new HashSet<Product>();
}
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
So now if you want all products in a category you can do something like:
var productsInCategory = db.Categorys
.Where(c => c.CategoryId == categoryId)
.SelectMany(c => c.Products);
If you do want an explicit junction tables see this: https://lostechies.com/jimmybogard/2014/03/12/avoid-many-to-many-mappings-in-orms/
You have to join the product and category tables with the bridge table Product_Category to retrieve the required product info.
using(eShopEntities db = new eShopEntities)
{
var products = (from p in db.Product_Category
join ProductTable pt on p.ID = pt.ProductID
join Category c on c.ID = P.CategoryID
select new
{
p.ID,
p.Name,
p.Description,
p.Price
}).ToList();
}

Is there a way to combine (JOIN) data from 2 tables together with SQLite?

I tried a few things to combine 2 tables, but the results returns only the data from the first table.
This are my tables:
[Table("Person")]
public class Person
{
[PrimaryKey, AutoIncrement]
public int PersonID { get; set; }
public string Name { get; set; }
public int CompanyID { get; set; }
}
[Table("Company")]
public class Company
{
[PrimaryKey, AutoIncrement]
public int CompanyID { get; set; }
public string Name { get; set; }
}
And this is my query:
var result = await _Connection.QueryAsync<Person>("SELECT * FROM Person JOIN Company ON Person.CompanyID = Company.CompanyID");
return result;
But it only gives the properties from the first table "Person". What did i forgot?
You forgot to use Present tense after did ;)
But actually this - _Connection.QueryAsync<Person> will return only Person fields because you specified a concrete Person type as a generic.
Create a 3rd class which has both Person and Company fields or use an anonymous type, then use something like this:
var query = from person in await db.Table<Person>().ToListAsync()
join company in await db.Table<Company>().ToListAsync()
on person.CompanyID = company.CompanyID
select new
{
Name = person.Name,
CompanyName = company.Name
// And so on
}
Note: this will load all records to the memory because of ToListAsync()
Update:
Instead of anonynous type, you can change your select to this:
PersonCompany personCompany = from person in .....
//---cut
on person.CompanyID = company.CompanyID
select new PersonCompany
{
Name = person.Name,
CompanyName = company.Name
// And so on
}

How to join two customer lists into one list

I have two classes:
1. a customer class, which contains the id and name of the customer
2. a customer_details class, which contain the address of the customer and so on
class customer
{
public int customer_id { get; set; }
public string name { get; set; }
//and so on
}
class customer_details
{
public int customer_id { get; set; }
public string address { get; set; }
//and so on
}
My question is, how can I join a List<customer> and a List<customer_details> to a single list, so it shows me the customer_id, name and address in a single list...
Thanks for your answers
You must use the Join Method
Here is an example with your classes
List<customer> customers = new List<customer>();
List<customer_details> details = new List<customer_details>();
var query = (from c in customers
join d in details on c.customer_id equals d.customer_id
select new
{
c.customer_id,
c.name,
d.address,
}).ToList();
Following is the example using Fluent syntax, which is rather compact and preferred:
customers.Join(
details,
c=>c.customer_id,
d=>d.customer_id,
(c,d)=>new {c.customer_id, c.name, d.address}
).ToList()

add a sql query result to a class

im trying to add a single row to a class using linq to sql.
i have a table (AdressesTable) wich contains a key named ID and an adress1 and adress2 column...
i created a class:
public class Adresses
{
public int ID { get; set; }
public int adress1 { get; set; }
public int adress2 { get; set; }
}
i created a datacontext and wrote a query
DBDataContext db = new DBDataContext();
Adresses adr = (from p in db.AdressesTable
where p.ID ==1
select p).First();
but it's not working... how can i add a sql query result to a class object?
You need to build a DbContext like this:
public class MyDbContext : DbContext
{
public DbSet<Addresses> Addresses { get; set; }
}
and then you can use it like this:
var db = new MyDbContext();
var adr = (from p in db.Addresses
where p.ID == 1
select p).First();

Categories

Resources