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()
Related
I have three tables as follows:
public class Employee
{
public Guid Id { get; set; }
public string FirstName { get; set; } = null!;
public string LastName { get; set; } = null!;
}
public class Answer
{
public Guid Id { get; set; }
public Guid QuestionId { get; set; }
public Guid AppraiserId { get; set; }//Employee who appraises
public Guid AppraisedId { get; set; }//Employee who has been appraised
}
public class FinalizedEmployee
{
public long Id { get; set; }
public Guid AppraiserId { get; set; }
public Guid AppraisedId { get; set; }
}
Every employee has an entry in the answers table by default. and when they answer all the questions we add a record in FinalizedEmployees.
Now I want to write a query to show all employees whether they have answered all the questions or not.
The output will be something like this:
Employee
Has answered all the questions
Employee 1
True
Employee 2
False
Employee 3
True
This is what I have tried so far:
var attendees = from answers in dbContext.Answers
join employees in dbContext.Employees
on answers.AppraiserId equals employees.Id
join finalize in dbContext.FinalizedEmployees
on answers.AppraiserId equals finalize.AppraisedId into finalized
from completed in finalized.DefaultIfEmpty()
where answers.AppraisalId == request.appraisalId
group employees by new { appraiser=answers.AppraiserId,hasComplete=completed!=null} into attendee
select new {attendee.Key.appraiser,attendee.Key.hasComplete };
The output is correct but only gives me employee Ids instead of the employee itself.
How can I write this query?
Is there any better way?
Every employee has an entry in answers table. and if they have answered all the questions there is a record in FinalizedEmployee table.
To check whether that the Employee has answered all the questions, you need a LEFT JOIN query for Employee to FinalizedEmployee tables.
With LEFT JOIN:
Guarantee all the records from Employee (LEFT) table will be queried.
If the employee's Id exists in FinalizedEmployee, the HasAnsweredAllQuestion will be true.
(from a in dbContext.Employees
join b in dbContext.FinalizedEmployees on a.Id equals b.AppraisedId into ab
from b in ab.DefaultIfEmpty()
select new
{
Id = a.Id,
Name = a.FirstName + " " + a.LastName,
HasAnsweredAllQuestion = b != null
}).ToList();
Another approach suggested by #Corey which was achieved with EXISTS will be:
(from a in dbContext.Employees
select new
{
Id = a.Id,
Name = a.FirstName + " " + a.LastName,
HasAnsweredAllQuestion = dbContext.FinalizedEmployees.Any(x => x.AppraisedId == a.Id)
}).ToList();
I want to fill a data in public IList<Order> OrderList { get; set; } with join 2 table. for that i have written a code in dbEntities below
using (var db = new dbEntities())
{
OrderList = (from row in db.Orders
join rowjoin in db.Users on row.UserId equals rowjoin.Id
orderby row.OrderNumber
select new { row.Id, row.UserId, row.TechnicianId, row.OrderNumber, row.ModelName,
row.ServiceName,row.IconUrl,row.Cost,row.Position, row.Status, rowjoin.FirstName ,
rowjoin.LastName, rowjoin.MobileNumber, rowjoin.Email,rowjoin.City, rowjoin.Address}).ToList();
}
its giving an error 2:
Cannot implicitly convert type System.Collections.Generic.List<AnonymousType#1> to System.Collections.Generic.IList<Mobileappy.Order>. An explicit conversion exists (are you missing a cast?)
How do i fix it?
Your query is not returning Order objects but an anonymous type.
If you want to get a List<Order> you must select row instead of select new {...}.
Your OrderList property needs to be a new type that can hold combination of both User and Order(like ViewModel). You can create properties for newly created type in two ways.
1. Create all required properties(User's properties + Order's proeperties) for newly created viewmodel and assign values thru the linq query.
public class OrderUserVM
{
public int OrderNumber { get; set; }
...
public string FirstName { get; set; }
...
}
public IList<OrderUserVM> OrderList { get; set; }
OrderList = (from row in db.Orders
join rowjoin in db.Users on row.UserId equals rowjoin.Id
orderby row.OrderNumber
select new OrderUserVM
{
OrderNumber = row.OrderNumber,
...
FirstName = rowjoin.FirstName,
....
}).ToList();
OR
2. Create only two properties of type 'User' and 'Order' for newly created viewmodel and assign values thru the linq query.
public class OrderUserVM
{
public User User { get; set; }
public Order Order { get; set; }
}
public IList<OrderUserVM> OrderList { get; set; }
OrderList = (from row in db.Orders
join rowjoin in db.Users on row.UserId equals rowjoin.Id
orderby row.OrderNumber
select new OrderUserVM
{
Order = row,
User = rowjoin,
}).ToList();
You need to declare a new Type (OrderUser) with the info of both the Order and the User. Then, instead of use select new {...} you must use select new OrderUser(){ UserName = rowjoin.FirstName, OrderId = row.Id, ... }. Change public IList<Order> OrderList { get; set; } by public IList<OrderUser> OrderList { get; set; }
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();
}
I am having trouble figuring out how to traverse a one to many relasionship using LINQ-To-SQL in my asp.net site that uses EF 5. I have made the relationships in the class files but when I try to go from parent to child in my where clause I am not given a list of the child columns to filter on. Can anyone tell me what is wrong with my code, I am new to EF and LINQ.
Product.cs:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Category Category { get; set; }
}
}
Category.cs:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual IList<Product> Products { get; set; }
}
Codebehind:
using (var db = new Compleate())
{
rpBooks.DataSource = (from c in db.Categories
where c.Products.Name == "Books"
select new
{
c.Name
}).ToList();
}
Do you want all products in the books category?
from p in db.Products
where p.Category.Name == "Books"
select new
{
p.Name
}
Or do you want to have all categories that contain products that are called called books?
from c in db.Categories
where c.Products.Contains( p => p.Name == "Books")
select new
{
c.Name
}
BTW, if you're only selecting the name, you can skip the anonymous type in the select part...
select p.name
Ok I had to update the codebhind to look like:
using (var db = new Compleate())
{
rpBooks.DataSource = (from c in db.Categories
join p in db.Products on c.ID equals p.id
where c.Products.Name == "Books"
select new
{
c.Name
}).ToList();
}
It should be name = c.Name it's not an issue with traversing, it's an issue with syntax, read the brief article on anonymous types here
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.