Below is the SQL Query I am trying to translate
SELECT dbo.Contracts.Supplier
FROM dbo.Contracts INNER JOIN dbo.Products ON dbo.Contracts.Product = dbo.Products.Product
where dbo.Products.ProductGroup='Crude'
GROUP BY dbo.Contracts.Supplier
Am I doing something wrong because I do not get same results with the following LINQ
var result = from c in context.Contracts
join p in context.Products on c.Product equals p.Product1
where p.Product1.Equals("Crude")
group c by c.Supplier into g
select new { supplier = g.Key };
It is generating a weird statement
SELECT
1 AS [C1],
[Distinct1].[Supplier] AS [Supplier]
FROM ( SELECT DISTINCT
[Extent1].[Supplier] AS [Supplier]
FROM [dbo].[Contracts] AS [Extent1]
WHERE N'Crude' = [Extent1].[Product]
) AS [Distinct1]
Using distinct would work but to get same results, LINQ should be generating a statement like so (it's like it is ignoring the join):
SELECT distinct dbo.Contracts.Supplier
FROM dbo.Contracts INNER JOIN dbo.Products ON dbo.Contracts.Product = dbo.Products.Product
where dbo.Products.ProductGroup='Crude'
I'm assuming that you are using 'EntityFramework' or 'Linq To SQL'. If so, you should be able to use navigation properties to navigate to product and filter invalit results out. This way your query might look something like this:
var result = (from c in context.Contracts
where c.Products.Any(p => p.ProductGroup == "Crude")
select c.Supplier).Distinct();
It will automatically convert into correct query (in this case possibly without join even, just using Exists sql keyword) and return distinct suppliers. This is if I understand your objective correctly - you want to obtain all suppliers assigned to contracts that contain product from 'Crude' product group.
Basically you should try to avoid using joins from linq to sql or linq to entities as much as possible when you can use navigation properties. System will probably be better at converting them into specific sql.
Related
I'm trying to join three tables together, but I just can't get my LINQ statements to get the data I want to. My SQL query that I want to replicate is like this:
SELECT TOP 5 SUM(Grade) AS 'TotalGrade', COUNT(Restaurants.Name) AS 'NumberOfVisits', Restaurants.Name FROM Lunches
JOIN dbo.LunchRestaurant ON Lunches.LunchId = LunchRestaurant.LunchId
JOIN Restaurants ON Restaurants.RestaurantId = LunchRestaurant.RestaurantId
GROUP BY Restaurants.Name
The LINQ statement I currently have is:
var q = from l in lunchContext.Lunches
join lr in lunchContext.LunchRestaurant on l.LunchId equals lr.LunchId
join r in lunchContext.Restaurants on lr.RestaurantId equals r.RestaurantId
select new { l.Grade, r.RestaurantId};
But with this one, I can't get in my group by statement or the aggregate functions no matter how I try. Do you have any suggestions on what to do? There also doesn't seem to be a way to write raw SQL statements when dealing with several tables, at least not easily done in EF Core if I'm not mistaken. Otherwise that'd be an option too.
I think you're looking for linq grouping. From memory, it would be something like;
var q = from l in lunchContext.Lunches
join lr in lunchContext.LunchRestaurant on l.LunchId equals lr.LunchId
join r in lunchContext.Restaurants on lr.RestaurantId equals r.RestaurantId
group l by lr.RestaurantId into g
select new { Id = g.Key, Grade =g.Sum(x=>x.Grade)};
If you do need to go down the raw SQL route then you can levarage ADO.Net like this
using (var command = lunchContext.Database.GetDbConnection().CreateCommand())
{
command.CommandText = "{Your sql query here}";
context.Database.OpenConnection();
using (var result = command.ExecuteReader())
{
// do something with result
}
}
I have the following SQL query. I would like to know how to write the same query in LINQ and C#.
select ph.Id,p.Id as projInfoId, ph.Title, ph.AdditionalHours, ph.AdditionalCost,
ph.InsertDate, ph.InsertBy, ph.LastUpdateDate, ph.LastUpdateBy, ph.TeamId,
ph.ProjInfoId
from tblTeamType t
join ProjInformation p on t.team_id = p.teamId
join projProject pj on p.projectId=pj.projectId
inner join ProjInfoAdditionalHrs ph on p.teamId = ph.teamId and p.Id = ph.proJinfoid
I think it is easier to translate SQL using query comprehension syntax instead of lambda syntax.
General rules:
Translate inner queries into separate query variables
Translate SQL phrases in LINQ phrase order
Use table aliases as range variables, or if none, create range
variables from table names abbreviations
Translate IN to Contains
Translate SQL functions such as DISTINCT or SUM into function calls
on the entire query.
Create anonymous objects for multi-column grouping or joining
Using these rules, you should get something like:
var ans = from t in tblTeamType
join p in ProjInformation on t.team_id equals p.teamId
join pj in projProject on p.projectId equals pj.projectId
join ph in ProjInfoAdditionalHrs on new { p.teamId, p.Id } equals new { ph.teamId, ph.proJinfold }
select new {
ph.Id,
projInfoId = p.Id,
ph.Title,
ph.AdditionalHours,
ph.AdditionalCost,
ph.InsertDate,
ph.InsertBy,
ph.LastUpdateDate,
ph.LastUpdateBy,
ph.TeamId,
ph.ProjInfoId
};
I'm trying to convert the following MySQL statement in to LINQ query format
SELECT * FROM table1 WHERE table1.id IN (SELECT c_id FROM table2 WHERE a_id IN (1, 49) GROUP BY c_id HAVING COUNT(*) = 2) ORDER BY name
Got as far as this, but I'm drawing a blank on how to handle the IN and 2nd SELECT statement
myItems = from c in table1
let id = c.id
where ????
orderby c.name
select c;
Would appreciate some guidance with this please
Try this:
var ids=new[]{1,49};
var innerquery=table2.Where(e=>ids.Contains(e.a_id))
.GroupBy(e=>e.c_id)
.Where(g=>g.Count()==2)
.Select(g=>g.Key);
var myItems = from c in table1
where innerquery.Contains(c.id)
orderby c.name
select c;
First define your inner query,after the group by you will get a collection of IGrouping<TKey, TElement>> that represent a collection of objects that have a common key, filter the groups choosing only those where count==2, and select the keys of those groups. The second part is really easy to understand. I split the process in two queries to do it more readable, but you can merge both query in one.
I am writing a simple LINQ query. Table structure is defined below:
Table A
Id int,
VName varchar2(20),
VAddress varchar2(200)
Table B
Id int,
NName varchar2(20),
NAddress varchar2(200)
LINQ Query
from c in A
join x in B on c.Id equals x.Id
order by A.Id
select New{
c.Id,
x.NName
}
Then SQL Generate as
select Filter1.Id,Filter1.NName from(
Select Extend1.Id,Extend1.VName,Extend1.VAddress,
Extend2.Id as Id1,Extend2.NName,Extend2.NAddress
from A as Extend1 Inner Join B as Extend2 on Extend1.Id=Extend2.ID)
as Filter1
MY Problem: I don't want select many columns in SubQuery.
If you're really worried about performance, then just use plain SQL... it's just about always faster than Linq (in my personal experience). Also, you can try using this Linq to execute your SQL:
IEnumerable<YourDataType> result = DataContext.ExecuteQuery<YourDataType>(SqlString);
You can find out more from the DataContext.ExecuteQuery<TResult> Method (String, Object\[\]) page at MSDN. Please note that this page relates to a different overload of this method, but it has examples in it.
I have question about use of Distinct with Entity Framework, using Sql 2005. In this example:
practitioners = from p in context.Practitioners
join pn in context.ProviderNetworks on
p.ProviderId equals pn.ProviderId
(notNetworkIds.Contains(pn.Network))
select p;
practitioners = practitioners
.Distinct()
.OrderByDescending(p => p.UpdateDate);
data = practitioners.Skip(PageSize * (pageOffset ?? 0)).Take(PageSize).ToList();
It all works fine, but the use of distinct is very inefficient. Larger result sets incur unacceptable performance. The DISTINCT is killing me. The distinct is only needed because multiple networks can be queried, causing Providers records to be duplicated. In effect I need to ask the DB "only return providers ONCE even if they're in multiple networks". If I could place the DISTINCT on the ProviderNetworks, the query runs much faster.
How can I cause EF to add the DISTINCT only the subquery, not to the entire resultset?
The resulting simplified sql I DON'T want is:
select DISTINCT p.* from Providers
inner join Networks pn on p.ProviderId = pn.ProviderId
where NetworkName in ('abc','def')
IDEAL sql is:
select p.* from Providers
inner join (select DISTINCT ProviderId from Networks
where NetworkName in ('abc','def'))
as pn on p.ProviderId = pn.ProviderId
Thanks
Dave
I dont think you need a Distinct here but a Exists (or Any as it is called in Linq)
Try this:
var q = (from p in context.Practitioners
where context.ProviderNetworks.Any(pn => pn.ProviderId == p.ProviderId && notNetworkIds.Contains(pn.Network))
orderby p.UpdateDate descending
select p).Skip(PageSize * (pageOffset ?? 0)).Take(PageSize).ToList();