Entity Sql for a Many to Many relationship - entity-framework

Consider two tables Bill and Product with a many to many relationship. How do you get all the bills for a particular product using Entity Sql?

Something like this
SELECT B FROM [Container].Products as P
OUTER APPLY P.Bills AS B
WHERE P.ProductID == 1
will produce a row for each Bill
Another option is something like this:
SELECT P, (SELECT B FROM P.Bills)
FROM [Container].Products AS P
WHERE P.ProductID == 1
Which will produce a row for each matching Product (in this case just one)
and the second column in the row will include a nested result set containing the bills for that product.
Hope this helps
Alex

You need to use some linq like this;
...
using (YourEntities ye = new YourEntities())
{
Product myProduct = ye.Product.First(p => p.ProductId = idParameter);
var bills = myProduct.Bill.Load();
}
...
This assumes that you have used the entitiy framework to build a model for you data.
The bills variable will hold a collection of Bill objects that are related to your product object.
Hope it helps.

Related

Many-To-Many relationships with EFCore and C# 5.0 : how to get the fields from the both of tables

I have the following database in PostgreSQL
EDIT: there is an Unique Key in PizzaTopping built with the fields Id_Pizza, Id_Topping
As you can see it's a Many-To-Many relationship.
When I ask Linqpad 6 to scaffold from my Database I have the following result:
The same result I have it when I use the EFCore Power Tools when I ask them to reverse engineer my database.
Reading from various sources, I've found, to ask EFCore to get the list of the toppings of the pizzas I should do something like that:
Pizzas.Where(p=>p.Description=="Margherita")
.Include(p=>p.PizzaToppings)
.ThenInclude(p=>p.IdToppingNavigation)
The query EFCore 5 returns this query:
SELECT P."Id_Pizza",
P."Description",
T0."Id_PizzaTopping",
T0."Id_Pizza",
T0."Id_Topping",
T0."Id_Topping0",
T0."Description"
FROM "Pizza" AS P
LEFT JOIN
(SELECT P0."Id_PizzaTopping",
P0."Id_Pizza",
P0."Id_Topping",
T."Id_Topping" AS "Id_Topping0",
T."Description"
FROM "PizzaTopping" AS P0
INNER JOIN "Topping" AS T ON P0."Id_Topping" = T."Id_Topping") AS T0 ON P."Id_Pizza" = T0."Id_Pizza"
WHERE P."Description" = 'Margherita'
ORDER BY P."Id_Pizza",
T0."Id_PizzaTopping",
T0."Id_Topping0"
Since I want to return a list with Pizza, topping like:
margherita, mozzarella
margherita, tomato sauce
marinara, garlic
marinara, tomato sauce
I tried with add .Select(topping=>topping.description) but it gets the pizza description.
So how can I take the toppings descriptions who they are in the topping table?
I tried to put a .Select() after the .ThenInclude() but I still see the Pizza entity and the p.PizzaToppings does not contain the property description of the topping table.
In this case you do not need Include but SelectMany with custom projection:
var query =
from p in Pizzas
from pt in p.PizzaToppings
select new
{
Pizza = p.Description,
Topping = pt.IdToppingNavigation.Description
}

How can I order an IQueryable based on a field that is in another table?

I am a newbie to LINQ and c# and I have two tables :
Products
ProductStoreds
ProductStore has a foreignKey to Products with a field named ProductId(same for both tables).
I have an IQueryable named result from Products table. how can I sort it based on a field named status in ProductStore Table.
this is what I have tried and I have not been successful:
result = result.Where(p =>
p.ProductId == DbContext.ProductStores.Select(m => m.Product)
.OrderByDescending(m => m.Status).ToInt());
You can join and order by Product like this
var stores = DbContext.ProductStores;
result = from store in stores
join product in result on product.ProductId equals store.ProductId
orderby store.Status
select product;

What does Query Projection mean in Entity Framework?

I am looking at some EF examples and trying to decipher what 'Query Projection' exactly equates to when doing LINQ to Entities or EntitySQL. I believe it is when the query results are filtered and projected into an anonymous type but not 100% sure.
Can someone please define this and maybe provide a small L2E query that uses an example of it?
Projection is when the result of a query is output to a different type than the one queried. Another article defined it as : the process of transforming the results of a query
Projection can be to an anonymous type, but could also be to a concrete type. If you come from a SQL world, it is akin to the columns listed in your SELECT clause.
Example selecting a sub-set of an object into an concrete type:
ParentObj.Select(x=> new ParentSlim { ParentID = x.ParentID, Name = x.Name } );
.
Example merging to object into a 3rd anonymous type:
Note: the select new portion is the projection.
from P in ParentObj.AsQueryable()
join C in ChildObj.AsQueryable() on P.ParentID == C.ParentID
select new { // <-- look ma, i'm projecting!
ParentID = P.ParentID,
Name = P.Name,
SubName = C.Name
RandomDate = DateTime.UtcNow()
}

Self m:n Relation

I have persons and a person can contact multiple other persons, so basically the "default" tables would be:
persons (id)
contacts (person1_id, person2_id)
With this schema, I'd have to issue queries like
SELECT *
FROM contacts c
WHERE ( person1_id = *id of person1* AND person2_id = *id of person2* )
OR
( person1_id = *id of person2* AND person2_id = *id of person1* )
to get the relation between two persons when I insert such a relation only once.
What is the common practice to deal with this situation?
Insert data once and do such an OR query
Insert the relation twice so that person1_id = id of person1 AND person2_id = id of person2 is enough
An entirely different approach?
Assuming:
The m:n table actually contains additional data, so if I create a relation for both ways, I'd have to duplicate the data
This is a core part of the application and most non-trivial queries involve at least a sub query that determines whether or not such a relation exists
If you write your insert logic such that person1_id < person2_id is true for all rows, then you can just write
SELECT *
FROM contacts c
WHERE person1_id = min(*id_of_person_1*, *id_of_person_2*)
AND person2_id = max(*id_of_person_1*, *id_of_person_2*)
Why don't you use Join between the tables?
something like this:
SELECT *
FROM contact c INNER JOIN person p ON p.id = c.person1_id
The the where and group bys you need to complete you're query =)
Take a look here how the results will be showed:
http://www.w3schools.com/Sql/sql_join_inner.asp
Regards,
Elkas
Try this one mate =)
SELECT c.person1_id as id_person_1, c.person2_id as id_person_2, p1.name as name_person_1, p2.name as name_person_2
FROM contact c
LEFT JOIN person p1 ON p1.id = c.person1_id
RIGHT JOIN person p2 ON p2.id = c.person2_id;
I don't know if it will work.. but give it try mate =)
"Insert the relation twice so that person1_id = id of person1 AND person2_id = id of person2 is enough"
That is how I'd do it, personally. It allows to deal with the situation where A has the contact details of B but not the other way around (e.g. a girl gives a guy her number at the bar saying "call me" as she walks out). It also makes the queries simpler.

Dynamic Query with Entity Framework 4

Okay I'm new to EF and I'm having issues grasping on filtering results...
I'd like to emulate the ef code to do something like:
select *
from order o
inner join orderdetail d on (o.orderid = d.orderid)
where d.amount > 20.00
just not sure how this would be done in EF (linq to entities syntax)
Your SQL gives multiple results per order if there's multiple details > 20.00. That seems wrong to me. I think you want:
var q = from o in Context.Orders
where o.OrderDetails.Any(d => d.Amount > 20.00)
select o;
I would do it like that:
context.OrderDetails.Where(od => od.Amount > 20).Include("Order").ToList().Select(od => od.Order).Distinct();
We are taking details first, include orders, and take distinct orders.