INNER JOIN in EF 4 - entity-framework

i have 2 tables master and details,
in EF 4 i want to write a query to retrieve a data like this t-sql
SELECT Table1.Table1ID, Table1.A, Table2.Table2ID, Table2.B
FROM Table1 INNER JOIN
Table2 ON Table1.Table1ID = Table2.Table1Id
i use this :
using(var context =new context())
{
var p = (from i in context.Table1.Include("Table2") select i);
}
but it returns rows in table1 how can i change it to retrieve rows in table2 and have my join?
thanks

I think you are looking for this:
var query = from a in context.Table1
join b in context.Table2 on a.Table1ID equals b.Table1Id
select new
{
a.Table1ID,
a.A,
b.Table2ID,
b.B,
};

Related

Sequelize: joining table on a subquery

I am trying to join a table on a subquery, but I don't know how to express it using Sequelize ORM. This is the raw SQL I want to run:
SELECT *
FROM table_a a
LEFT OUTER JOIN (SELECT * FROM table_b b WHERE col = VAL) ON a.id = b.id;
I tried
A.findAll({
include: [
{
model: B,
where: { col: val },
}
]
}).then(...);
but that doesn't get me the query I want. Instead it changes the join to an INNER JOIN, and joins on col = VALUE instead. Is there a way to do a join on the result of a subquery? I am using Postgres if it matters.
Update: After making the following change, the resulting query now uses a LEFT OUTER JOIN as expected:
include: [
{
model: B,
where: { col: val },
required: false,
}
]
However, it is still joining on col = VALUE, the generated query looks like:
SELECT * FROM table_a a
LEFT OUTER JOIN table_b b ON a.id = b.id AND b.col = VALUE;
These 2 queries ARE functionally equivalent:
SELECT * FROM table_a a
LEFT OUTER JOIN (SELECT * FROM table_b b WHERE col = VAL) ON a.id = b.id;
SELECT * FROM table_a a
LEFT OUTER JOIN table_b b ON a.id = b.id AND b.col = VALUE;
There is NO ADVANTAGE from the first one whatsoever. So, if the first one provides the wanted results, so should the second one.

linq subquery join and group by

Hi is it possible to translate the below queries into linq ? ...
I am using entity frameworks core and tried to use the stored procedure but it seems like i have to create a model that applies to the metadata of the stored procedure. So i am trying to understand whether this kinda such query can be translated into linq so i don't have to create a separate db model.
SELECT
Stock.stockID ProductID,
stockName ProductName,
categoryName ProductCategory,
typeName ProductType,
sizeName ProductSize,
currentQuantity CurrentQuantity,
standardQuantity QuantityPerBox,
CONVERT(VARCHAR(255),CONVERT(INT,Stock.price)) AvgUnitCost,
CONVERT(VARCHAR(255),CONVERT(INT,x.lastUnitCost)) LastOrderUnitCost,
CONVERT(VARCHAR(10),CONVERT(DATE,x.lastOrderDate)) LastOrderDate
FROM dbo.Stock
LEFT JOIN
(
SELECT stockID,unitPrice lastUnitCost ,orderDate lastOrderDate, ROW_NUMBER() OVER (PARTITION BY stockID ORDER BY orderDate DESC) rn FROM dbo.SalesOrder
JOIN dbo.SalesOrderDetail ON SalesOrderDetail.salesOrderID = SalesOrder.salesOrderID
WHERE customerID = #customerID AND salesStatus = 'S'
) x ON x.stockID = Stock.stockID AND rn = 1
LEFT JOIN dbo.StockCategory ON StockCategory.stockCategoryID = Stock.stockCategoryID
LEFT JOIN dbo.StockType ON StockType.stockTypeID = Stock.stockTypeID
LEFT JOIN dbo.StockSize ON StockSize.stockSizeID = Stock.stockSizeID
WHERE disStock = 0
Almost everything is possible. you just need to be careful with performance.
var query =
from stock in db.Stocks
join x in (
from grp in (
from so in db.SalesOrders
join sod in db.SalesOrderDetails on so.SalesOrderId equals sod.SalesOrderId
where so.CustomerId == customerId && so.SalesStatus == "S"
orderby so.OrderDate descending
select new {
sod.StockId,
LastUnitCost = sod.UnitPrice,
LastOrderDate = so.OrderDate
} into inner
group inner by inner.StockId)
select grp.Take(1)) on x.StockId equals stock.StockId into lastStockSales
from x in lastStockSales.DefaultIfEmpty()
join sc in db.StockCategories on stock.StockCatergotyId equals sc.StockCategoryId into scLeft
from sc in scLeft.DefaultIfEmpty()
join st in db.StockTypes on stock.StockTypeId equals st.StockTypeId into stLeft
from st in stLeft.DefaultIfEmpty()
join ss in db.StockSizes on stock.StockSizeId equals ss.StockSizeId into ssLeft
from ss in ssLeft.DefaultIfEmpty()
where stock.DisStock == 0
select new MyDTO {
ProductId = stock.StockId,
ProductName = stock.StockName,
ProductType = st.TypeName,
ProductSize = ss.SizeName,
CurrentQuantity = stock.CurrentQuantity,
QuantityPerBox = stock.StandardQuantity,
AvgUnitCost = stock.Price,
LastOrderUnitCost = x.LastUnitCost,
LastOrderDate = x.LastOrderDate
};
As you can see is easy to rewrite these queries, I had to change a little bit the logic on how to get the latest sales for a stock item since ROW_NUMBER() OVER (PARTITION... is not supported from a LINQ perspective. Again, you would have to consider performance when rewriting queries.
Hope this helps.

Linq to SQL self join where right part of join is filtered

I am trying to map a self join where the right table must be filtered, e.g. SQL such as this:
select t2.* from table t
left join table t2
on t2.parentID = t.ID and t2.active=1;
I can figure out the syntax if I wanted to filter the left table:
// works
var query = from t in table
where t.active= 1
join t2 in table
on t.parentID equals t2.ID into joined
from r in joined.DefaultIfEmpty() ...
But I can't figure out how to filter the right table. It seems like it should be something like this...
// does not work
var query = from t in table
join t2 in table
where t.field = 1
on t.parentID equals t2.ID into joined
from r in joined.DefaultIfEmpty() ...
(not valid... join can't have where). There is discussion of using multiple from clauses, but if I create more than one from clause, so I can add a where to the 2nd one, I can't figure out how to join the results of them into a new temporary table.
I can't just add a "where" after the join; the right table must be filtered first or matches will occur, and a where clause at the end would remove the row from the left table that I do want in the output. That is, the output should have rows where there's nothing matched from filtered right table. So I need to filter the right table before the join.
I think you are looking to do this:
var query = from t in table
join t2 in
(from t3 in table
where t3.field = 1
select t3)
on t.parentID equals t2.ID into joined
from r in joined.DefaultIfEmpty() ...
Another way is to use multiple from like this:
var query = from t in table
from t2 in table.Where(x => x.field = 1)
.Where(x => x.ID == t.parentID)
.DefaultIfEmpty()
select ....

Entity SQL selecting from more then 3 tables

I am new to Entity framwork and currently trying hard to get used this programming paradigm. I have this query which i want to write in Entity SQL.
SELECT f.id, f.personName, c.Category, j.busCode, s.description, f.StartDate, (SELECT COUNT(*) FROM Analysis WHERE id = f.id) As numOfAnalysis
FROM forms f
INNER JOIN Jobs j ON f.id = j.id
INNER JOIN category c ON j.categoryid = c.categoryid
INNER JOIN stage s ON f.stageid = s.stageid
WHERE j.busCode NOT IN ('xyz', 'YYY')
ORDER BY startDate
I can get records from two tables but as soon as i add third table using the navigation property, i get error table category is not loaded in the current context. I am using .net 3.5. Keep in mind that EDM V2 doest not have foreign keys and i think the only way to traverse through the table relationship is navigation property.
Any help will be deeply appreciated.
Thanks
Coder74
If you use should be able to mount this Linq query.
I tried to put together, but in the rush and no such test is complicated.
You can use this reference as support: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
var result = (from f in forms
join j in Jobs on f.id equals j.id
join c in Category on j.categoryid equals c.categoryid
join s in stage on f.stageid equals s.stageid
join a in Analysis on a.id equals f.id
where !(new int[] { 'xyz', 'YYY' }).Contains(j.busCode)
orderby f.StartDate
select {
id =f.id,
personName = f.personName,
Category = c.Category,
busCode = j.busCode,
description = s.description,
StartDate = f.StartDate,
numOfAnalysis = a.Count()
}).ToList()
Julio Spader
W&S Soluções de Internet

Entity Framework 4 INNER JOIN help

Can anyone tell me how to write the following query in Entity Framework 4.0? "Blogs" and "Categories" are my entities. The query basically returns me the list of categories and the number of blogs that are in that category.
SELECT b.CategoryId, c.Value, Count(b.Id) AS [Count] FROM dbo.Blogs b
INNER JOIN dbo.Categories c ON b.CategoryId = c.Id
GROUP BY b.CategoryId, c.Value
Thanks in advance.
The following should work (LinqToEntities):
var categories = from c in oc.Categories
select new
{
CategoryId = c.Id,
c.Value,
Count = c.Blogs.Count()
}
This will give you a list of category ids and values and for each category id you get the number of blogs in that category.
EDIT: To give an answer to the question in your comment: this isn't possible in LinqToEntities but you can do it in Entity SQL.
var results = new ObjectQuery<DbDataRecord>(
#"SELECT y, COUNT(y)
FROM MyEntities.Blogs AS b
GROUP BY YEAR(b.CreatedDate) AS y", entities).ToList();
var nrBlogsPerYear = from r in results
select new { Year = r[0], NrBlogs = r[1] };
In the Entity SQL query, you should replace MyEntities with the name of your context.
EDIT: As I just found out through a comment by Craig, grouping by year is possible in L2E so you can write your query like this:
var nrBlogsPerYear = from b in oc.Blogs
group b by b.CreatedDate.Year into g
select new { Year = g.Key, NrBlogs = g.Count() };
If you have navigation properties in your entities, you can do that :
var cats = from c in db.Categories
let count = c.Blogs.Count()
where count > 0
select new
{
CategoryId = c.Id,
Value = c.Value,
Count = count
};
If you prefer to use an explicit join, you can do it like that :
var cats = from c in db.Categories
join b in db.Blogs on c.Id equals b.CategoryId into g
select new
{
CategoryId = c.Id,
Value = c.Value,
Count = g.Count()
};
var query = from p in B.Products
join c in B.Categories on p.CategoryID equals c.CategoryID
orderby c.CategoryName,p.ProductName
select new
{
c.CategoryName ,
p.ProductName,
p.ReorderLevel
};
GridView1.DataSource = query.ToList();
GridView1.DataBind();