I have 3 tables. Basically, I have this structure:
Customer
--------
IDCustomer
NameCustomer
Product
«««««««
IDProduct
NameProduct
Order
«««««
IDCustomer
IDProduct
How to get a result like this, using LINQ:
Result
««««««
NameCustomer
NameProduct
Thanks in advance!
Assuming you don't have proper relationships set up in the database (or you haven't generated navigation properties for your relationships), you could do the following:
var result = from c in _context.Customer
join o in _context.Order on c.IDCustomer equals o.IDCustomer
join p in _context.Product on o.IDProduct equals p.IDProduct
select new { c.NameCustomer, p.NameProduct }
It would be much easier, though, to add the proper foreign keys to the database and allow Entity Framework (or LINQ to SQL) generate the navigation properties for you. If that were the case, it would be as easy as:
var result = _context.Order.Select(o => new
{
o.Customer.NameCustomer,
o.Product.NameProduct
});
The whole beauty of LINQ is that this should be all automatically done for you with automatically generated objects.
Make sure your table relationships are setup in SQL Server before moving them to your DBML file. After this, your Customer table will have Orders attached to it, in which your Products will be attached to your orders.
Such as selecting from your customer table (LINQ) will give you a list of Customers, in which will have an IENumerable list of Order objects attached to each.
from t1 in Product
join t2 in Order on t1.IDProduct equals t2.IDProduct
join t3 in Customer on t2.IDCustomer equals t3.IDCustomer
select new { t1.NameProduct, t3.NameCustomer}
you can use linqpad.exe to test your linq query directly against your database
Related
I would like to SELECT the categories in my table product_category through the table categories.
I have a FK many to many between product and category so the table product_category has been created dynamically.
I found that code for get the information in the other table when the FK is not directly in the table I am :
->join(ProductComponentSupplier::class, "pcs", \Doctrine\ORM\Query\Expr\Join::WITH, "p.id = pcs.product")
But in this case, ProductComponentSupplier is a class so it's accessible that way.
I would like to know if there is a way in DQL to get the information or I have to use SQL.
In SQL would be :
SELECT *
FROM category
LEFT JOIN product_category ON category.id = product_category.category_id
I hope I was clear.
Thank you so much for your help.
Take a common business situation in which you have a table of orders with a created_date and a customer_id. You want to read all the orders this month along with the associated customer so:
#Query("select Q from Order Q join customer C on Q.customer_id=C.id where Q.created_date >= '2021-11-01'")
This works but when I added to application.properties:
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
I was horrified to observe that for each order, the customer details are re-read with a separate select statement; thus, if there are say 80 orders this month, the JPA system executes 81 select statements, not one. I appreciate that this might be hard to optimise-out in the general case but it makes the system useless for production. Is it possible to give hints to JPA/Spring to avoid the extra select statements?
This answer works for me and makes sense. If you're JOINing two tables then the resultant rows are of a new type, distinct from the type of the rows of the underlying tables. So you have to declare that type:
data class OrderwithCust (
var orderid: Int,
var customerid: Int,
var customerName: String?
)
You can then obtain a list of OrderwithCust instances via
#Query("select new OrderwithCust(Q.id,Q.customer_id,C.name) from Order Q join customer C on Q.customer_id=C.id where Q.created_date >= '2021-11-01'")
I am using linqpad. I have an ODATA connected. The entities are listed in left pane with relationships. There are two entities called Products and Customers. I have to get all the product id starting with pid and names of all customers startin with b. There is a relationship between both. Product is a child of customer. How do I do? I am trying since two days but unable to figure it out. Anyone could help?
this is the base code. i dont no what to do further.
from p in products
where p.ProductId.StartsWith("Pid")
from c in customers
where c.Name.StartsWith("B")
select new
{
p.Pid,
c.Name
};
Can you please specify how you want the relation between the two entities to affect the result of the query? Do you expect the above to only returns products (with ID starting with a given value) and then only the customers for those products which name starts with a certain value?
Such a query is not expressible in OData unfortunately. You could request all products which ID starts with a specific value, and all the related customers. And then filter the customers on the client.
For example this will get you all the products which ID starts with a certain value and all their customers:
from p in products
where p.ProductId.StartsWith("Pid")
select new Product
{
ProductId = p.ProductId,
Customers = p.Customers
};
So, I once again seem to have an issue with MS Access being finicky, although it seems to also be an issue when trying similar queries in SSMS (SQL Server Management Studio).
I have a collection of tables, loosely defined as follows:
table widget_mfg { id (int), name (nvarchar) }
table widget { id (int), name (nvarchar), mfg_id (int) }
table widget_component { id (int), name (nvarchar), widget_id (int), component_id }
table component { id (int), name (nvarchar), ... } -- There are ~25 columns in this table
What I'd like to do is query the database and get a list of all components that a specific manufacturer uses. I've tried some of these queries:
SELECT c.*, wc.widget_id, w.mfg_id
FROM ((widget_component wc INNER JOIN widget w ON wc.widget_id = w.id)
INNER JOIN widget_manufacturer wm on w.mfg_id = wm.id)
INNER JOIN component c on c.id = wc.component_id
WHERE wm.id = 1
The previous example displays duplicates of any part that is contained in multiple widget_component lists for different widgets.
I've also tried doing:
SELECT DISTINCT c.id, c.name, wc.widget_id, w.mfg_id
FROM component c, widget_component wc, widget w, widget_manufacturer wm
WHERE wm.id=w.mfg_id AND wm.id = 1
This doesn't display anything at all. I was reading about sub-queries, but I do not understand how they work or how they would apply to my current application.
Any assistance in this would be beneficial.
As an aside, I am not very good with either MS Access or SQL in general. I know the basics, but not a lot beyond that.
Edit:
I just tried this code, and it works to get all the component.id's while limiting them to a single entry each. How do I go about using the results of this to get a list of all the rest of the component data (component.*) where the id's from the first part are used to select this data?
SELECT DISTINCT c.part_no
FROM component c, widget w, widget_component wc, widget_manufacturer wm
WHERE(((c.id=wc.component_id AND wc.widget_id=w.id AND w.mfg_id=wm.id AND wm.id=1)))
(P.S. this is probably not the best way to do this, but I am still learning SQL.)
What I'd like to do is query the database and get a list of all
components that a specific manufacturer uses
There are several ways to do this. IN is probably the easiest to write
SELECT c.*
FROM component c
WHERE c.id IN (SELECT c.component_id
FROM widget w
INNER JOIN widget_component c
ON w.id = c.widget_id
WHERE w.mfg_id = 123)
The IN sub query finds all the component ids that a specific manufacturer uses. The outer query then selects any component.id that is that result. It doesn't matter if its in there once or 1000 times it will only get the component record once.
The other ways of doing this are using an EXISTS sub query or using a join to the query (but then you do need to de-dup it)
It sounds like your component -to- widget relationship is one-to-many. Hence the duplicates. (i.e., the same component is used by more than one widget).
Your Select is almost OK --
SELECT c.*, wc.widget_id, w.mfg_id
but the wc.widget_id is causing the duplicates (per the assumption above).
So remove wc.widget_id from the SELECT, or else aggregate it (min, max, count, etc.). Removing is easier. If you agregate, remember to add a group by clause.
Try this:
SELECT DISTINCT c.*, w.mfg_id
Also -- FWIW, it's generally a better practice to use field names, instead of the *
I am using Entity Framework 4.1 using the Code First approach. I have two entities that exhibit a parent-child relationship. To provide a concrete example, imagine I have a Category entity that has zero-to-many Product entities associated with it. I have set up navigation properties on both sides (in my example, the Category entity would have an ICollection<Product> property while the Product entity has a Category property).
Now, when I get Category entities I want to also get back a count of the number of children records for each category. I am aware I can do:
Category category = dbContext.Categories.Single(...);
int productCount = category.Products.Count();
But I am concerned because the resulting SQL that gets sent to the database depends on whether I use lazy or eager loading.
In the first case (lazy loading), the call to the Products collection prompts EF to run a SQL query like:
SELECT ... all columns ...
FROM Products
WHERE CategoryID = #CategoryID
In the second case (eager loading), the products are loaded when the category information is retrieved so there is no second query to the database, but the downside is that if I'm not at all interested in products (other than their count) then I'm bringing back a lot of unneeded data.
What I'd like it to have the best of both worlds: namely, the ability to have just one database query and one that uses SELECT COUNT(*) rather than one that gets all of the columns from the table. In short, I'd like SQL like the following to be sent to the database:
SELECT ... all category columns ...,
(SELECT COUNT(*) FROM Products p WHERE p.CategoryID = c.CategoryID)
FROM Categories c
WHERE c.CategoryID = ...
Is that at all possible with EF or is what I want a pipe dream?
Not sure, but maybe try this:
var result = db.Categories.Where(x => x.CategoryId == categoryId)
.Select(y => new
{
Count = y.Products.Count(),
Category = y
})
.Single();
//result.Count
//result.Category
Yes, this is possible with EF. You can also create a view model to show the information with the child counts as properties. This article cover how to do that.
http://www.ozkary.com/2015/04/entity-framework-associated-table.html