I'm developing an ASP .NET WEB API using entity framework. I have an SQL code which I have to rewrite in LINQ I tried different approaches but none did work. The code is as follows:
SELECT
Debit, Credit,
(SELECT SUM(q.debit - q.Credit)
FROM Qry013 q
WHERE q.AccountGuide = 'D23265D8-E39A-4AF0-B652-0608FA61A866'
AND q.EntryNumber <= qry013.EntryNumber
AND q.ID <= qry013.ID) AS balance,
ISNULL(Entryname, InvoiceName) AS source,
ISNULL(EntryNumber, BillNumber) ASTransactionNumber,
TBL001.CurrencyShortcut AS CurrencyName,
Qry013.Rate, CostCenterName, BranchName,
EntryNote
FROM
Qry013
INNER JOIN
TBL001 ON TBL001.CardGuide = Qry013.CurrencyGuide
WHERE
AccountGuide = 'D23265D8-E39A-4AF0-B652-0608FA61A866'
AND Posted = 1
Everything might seem easy but that part where there is a nested SELECT with a SUM operation. I really appreciate your help
I solved this by adding a model class in which I defined the properties of the specific columns in the sql query and I used it as an object to populate the data in.
Related
I need to achieve this next SQL query using the Exposed framework from Jetbrains
select r.name
from recipes r
inner join ingredient_index i on i.recipe_id = r.recipe_id
where i.ingredient_id IN (7, 5)
GROUP BY r.name
HAVING COUNT(*) = 2
This is taken directly from this answer, and the result from the query in native SQL is exactly what I'm looking for, but I'm using Exposed framework on my backend.
Stackoverflow question
I'm having issues with the last part HAVING COUNT(*) = X
I see there's a method I can use that's query.having { } but I don't see how I could implement the COUNT(*) = X inside that expression.
Any help is appreciated.
I have this SQL query which is really complex to me and I tried to convert it to EntityFramework Core code based, but I couldn't do at least the multiple join.
SELECT vrCore_Product.iMasterId, vrCore_Product.sName[Particular],
SUM(tCore_Indta_0.fQuantityInBase) - ISNULL(AVG(tCore_ReservedStock_0.fQuantity),0)[Net Quantity],vrPos_Outlet.iMasterId[Product]
,vrCore_Product.sCode[vrCore_Product.sCode0] FROM tCore_Data_0
JOIN tCore_Header_0 ON tCore_Header_0.iHeaderId = tCore_Data_0.iHeaderId
JOIN tCore_Indta_0 ON tCore_Data_0.iBodyId = tCore_Indta_0.iBodyId
JOIN cCore_Vouchers_0 WITH (READUNCOMMITTED) ON tCore_Header_0.iVoucherType = cCore_Vouchers_0.iVoucherType
JOIN vrCore_Product ON vrCore_Product.iMasterId = tCore_Indta_0.iProduct AND vrCore_Product.iTreeId = 0
JOIN vrPos_Outlet ON vrPos_Outlet.iMasterId = tCore_Data_0.iInvTag
LEFT JOIN
(
Select iProduct, tCore_Data_0.iInvTag, SUM(case bReserveOrRelease when 0 then tCore_ReservedStock_0.fQuantity else -tCore_ReservedStock_0.fQuantity end) fQuantity
FROM tCore_ReservedStock_0
JOIN tCore_Data_0 ON tCore_Data_0.iTransactionId = tCore_ReservedStock_0.iTransactionId
JOIN tCore_Indta_0 ON tCore_Indta_0.iBodyId = tCore_Data_0.iBodyId
JOIN tCore_Header_0 ON tCore_Header_0.iHeaderId = tCore_Data_0.iHeaderId
WHERE tCore_Header_0.bSuspended = 0
GROUP BY iProduct,tCore_Data_0.iInvTag
HAVING SUM(CASE bReserveOrRelease WHEN 0 THEN tCore_ReservedStock_0.fQuantity ELSE -tCore_ReservedStock_0.fQuantity END)<>0
)tCore_ReservedStock_0 ON tCore_ReservedStock_0.iProduct = tCore_Indta_0.iProduct AND tCore_ReservedStock_0.iInvTag = tCore_Data_0.iInvTag WHERE tCore_Header_0.bUpdateStocks = 1 AND tCore_Data_0.bSuspendUpdateStocks <> 1
AND tCore_Header_0.bSuspended = 0 AND tCore_Data_0.iAuthStatus < 2
AND (tCore_Header_0.iDate BETWEEN dbo.DateToInt('2020-01-10') AND dbo.DateToInt('2020-01-22') OR (tCore_Header_0.iDate < dbo.DateToInt('2020-01-22') AND tCore_Header_0.iVoucherClass = 512)) AND vrCore_Product.iProductType <> 'Service' AND vrPos_Outlet.iMasterId IN (26) GROUP BY vrPos_Outlet.iMasterId, vrCore_Product.iMasterId, vrCore_Product.sName ,vrCore_Product.sCode HAVING SUM(tCore_Indta_0.fQuantity) <> 0 ORDER BY vrPos_Outlet.iMasterId
We think in objects when we code in C#. We think relational when we do T-SQL. This creates a problem called object-relational impedance mismatch. EF helps break that problem by allowing us to think only in objects. You are trying to do the exact opposite, which is translate a query back to an object representation, via a Linq query. Here's a tip: I never do that. My starting point is the C# object model and I model the query thinking in Linq. I don't care about T-SQL.
This might seem like just a matter of syntax, since both T-SQL and Linq are query languages, and in the end, Linq gets translated to T-SQL by EF. However, the difference between them is not only syntax, but the way we think. For instance, while we think about joins in T-SQL, in linq, we think about navigation properties. On one, we think about relations and foreign keys, on the other, we think about objects and graphs.
In the very rare case where I'm better off with a T-SQL query, I rather execute a raw query instead of going through the pain of translating it back to Linq: https://learn.microsoft.com/en-us/ef/core/querying/raw-sql
In your case I would do either of the following 2 things:
I would either simply throw away the T-SQL query and start over, thinking in Linq. It helps if I have a good understanding of the business domain and what I need to extract using that query. This is most of the time, favourite approach.
Or, in case I'm too committed to the query (pun not intended), I would simply execute it as a raw query using EF (always using parameters instead of concatenating the query with input values, in order to prevent any Sql Injection vulnerability). The only downside to this that your code stops being database engine independent the moment you add a raw query to it.
If you have relationships, you just can use Include() like
var data = _context.TcoreData0
.Include(x => x.TcoreHeader0)
.Include(x => x.TcoreIndta0)
.Include("tCore_Header_0.cCore_Vouchers_0")
.Include...
i'm stuck at another point in my little Access 2016 Database. My code looks like the following and i know it probably isn't the cleanest solution but i'm kinda new to this and i tried to educate myself and get some help here already.
I'm trying to play around with the reports now a little bit and i am using this test query which returns all entries of two tables joined together.
As far as i could find out I have this one subquery included that returns the prvious day inventory for each record and that is most likely the cause of my error. I found a possible solution with adding SELECT * FROM at the beginning of my code but i get a Syntax error when i do that and i'm not sure how to solve this problem.
here's my code
SELECT Stations.StationName, Product.ProductName, GasInventoryTransactions.TransactionDate, (SELECT TOP 1 Dupe.ActualInventory FROM GasInventory AS Dupe WHERE Dupe.StationID = Stations.StationID AND Dupe.ProductID = Product.ProductID AND Dupe.InventoryDate < GasInventory.InventoryDate ORDER BY Dupe.InventoryDate DESC) AS PreviousDayInventory, GasInventory.ActualInventory, GasInventoryTransactions.GasSales, GasInventoryTransactions.GasDelivery, [PreviousDayInventory]+[GasDelivery]-[GasSales] AS BookBalance, GasInventory.ActualInventory, [ActualInventory]-[BookBalance] AS OverShort
FROM (Stations INNER JOIN (Product INNER JOIN GasInventory ON Product.[ProductID] = GasInventory.[ProductID]) ON Stations.[StationID] = GasInventory.[StationID]) INNER JOIN GasInventoryTransactions ON GasInventory.[InventoryDate] = GasInventoryTransactions.[TransactionDate];
thanks for your help!
I searched online and found out many had the same problem, but non of the solutions worked for me.
I'm really hoping you could help me:
I have this ORACLE SQL query that is working fine in PL/SQL:
select a.bzq_terminate_provider, a.callsnum, a.at_call_dur_sec, sum_charge
From (select * from usage_cycle_sum
where ban='80072922' and ben='1'
and subscriber_no='036585305'
and start_cycle_code ='20150207'
and feature_code_rank='1') a, (select bzq_terminate_provider,sum(charge_amount) as sum_charge from usage_cycle_sum
where ban='80072922' and ben='1'
and subscriber_no='036585305'
and start_cycle_code ='20150207' group by bzq_terminate_provider) b
where a.bzq_terminate_provider=b.bzq_terminate_provider
I also tried this other version that works fine as well:
select PROVIDER,sum(CALLS),sum(CHARGE),sum(DUR)
from (
select bzq_terminate_provider PROVIDER,callsnum CALLS,charge_amount CHARGE,at_call_dur_sec DUR
from usage_cycle_sum
where ban='80072922' and ben='1'
and subscriber_no='036585305'
and start_cycle_code ='20150207'
and feature_code_rank='1'
union
select bzq_terminate_provider PROVIDER,0 CALLS,charge_amount CHARGE,0 DUR
from usage_cycle_sum
where ban='80072922' and ben='1'
and subscriber_no='036585305'
and start_cycle_code ='20150207'
and feature_code_rank='2'
)
group by PROVIDER
My problem is that when i create a datagrid in Visual Studio web application, i get an error: syntax error: expecting identifier or quoted identifier
The connection is ok, i checked the simple select queries as well as the whole union part in the second query i attached, they work!
But when i use those two versions, i get this error.
What can be the problem? Is there another way to solve this?
Thanks.
EDIT 21/06/2015
It seems that visual studio doesn't work well with complex queries and i'm still looking for a solution for this, since my next queries are more complex...
Your second query is so much nicer to write as:
select bzq_terminate_provider as PROVIDER, sum(callsnum) as CALLS,
sum(charge_amount) as CHARGE, sum(at_call_dur_sec) as DUR
from usage_cycle_sum
where ban = '80072922' and ben = '1' and
subscriber_no = '036585305' and
start_cycle_code ='20150207' and
feature_code_rank in ('1', '2')
group by bzq_terminate_provider ;
Or, perhaps the select needs to be:
select bzq_terminate_provider as PROVIDER,
sum(case when feature = '1' then callsnum else 0 end) as CALLS,
sum(charge_amount) as CHARGE,
sum(case when feature = '1' then at_call_dur_sec else 0 end) as DUR
(The first version assumed that the fields were zeroed out in the second subquery because they are NULL in the data, but that might not be true.)
However, application software is not yet smart enough to identify such awkwardly written queries, so that is not the actual problem you are facing. If the query works in the database, but not in the application, then typical problems are:
The application is not connected to the right database.
The application does not have permissions on the database or table.
The application query is different from the query run in the database, typically due to some substitution problem.
The results from running the query in the application are not being interpreted correctly.
I am currently working on a project using NHiberate as the DAL with .NET 2.0 and NHibernate 2.2.
Today I came to a point where I had to join a bunch of entities/collections to get what I want. That is fine.
What got me was that I do not want the query to return a list of objects of a certain entity type but rather the result would include various properties from different entities.
The following query is not what I am doing but it is kind of query that I am talking about here.
select order.id, sum(price.amount), count(item)
from Order as order
join order.lineItems as item
join item.product as product,
Catalog as catalog
join catalog.prices as price
where order.paid = false
and order.customer = :customer
and price.product = product
and catalog.effectiveDate < sysdate
and catalog.effectiveDate >= all (
select cat.effectiveDate
from Catalog as cat
where cat.effectiveDate < sysdate
)
group by order
having sum(price.amount) > :minAmount
order by sum(price.amount) desc
My question is, in this case what type result is supposed to be returned? It is certainly not of type Order, neither is of type LineItems.
Thanks for your help!
John
you can always use List of object[] for returning data and it will work fine.
This is called a projection, and it happens any time you specify an explicit select clause that contains rows from various tables (or even aggregate / summary data from a single table).
Using LINQ you can create anonymous objects to store these rows of data, like this:
var crunchies = (from foo in bar
where foo.baz == quux
select new { foo.corge, foo.grault }).ToList();
Then you can do crunchies[0].corge for example to pull out the rows & columns.
If you are using NHibernate.Linq this will "just work".
If you're using HQL or Criteria API, then what Fahad mentioned will work. You'll get a List<object[]> as a result, and the index of the array references the order of the columns that you returned in your select clause.