I've got a linq statement like this:
this.DataContext.TableName.Where(r => r.Field =="REQUEST" || r.Field== "UPDATE")
The statement when converted to sql looks like this:
WHERE ([Extent1].[Field] IN (N'REQUEST',N'UPDATE'))
rather than:
WHERE Field = 'REQUEST' or Field = 'UPDATE'
The bottom example runs twice as fast as the top. Is anyone able to point me in the right direction in order to get the converted SQL to look like the below example.
I'm using C# ASP.Net MVC 5, EF6, but whatever I seem to try just gives the same results and uses the IN statement.
I use LINQPad4 with:
Customers.Where(x => x.Name == "Tom" || x.Name == "Dick").Dump()
Generate:
-- Region Parameters
DECLARE #p0 NVarChar(1000) = 'Tom'
DECLARE #p1 NVarChar(1000) = 'Dick'
-- EndRegion
SELECT [t0].[ID], [t0].[Name]
FROM [Customer] AS [t0]
WHERE ([t0].[Name] = #p0) OR ([t0].[Name] = #p1)
IN vs OR is discussed here: IN vs OR in the SQL WHERE Clause
Hope this helps.
In this case if the concern is performance well, you have a big long list of articles to read to have your own opinion. For once maybe you have to concern about if your column needs and index and if your statistics are updated.
If your values are request and update as a string, evaluate if you need a related table to hold this values and have a related id in your table with an integer value. This int column can have an index and this will provide better performance and a smaller footprint in your data and index size.
LINQ will try to provide the best execution based in your database structure. So for instance if you provide a good design in your database you dont have to bother in most cases of what is the result sql from the linq query. (both in big querys and with big databases always make this check, and check the execution plan)
I want to make use of the Convert function in SQL Server 2008 so I can search on a DateTime column.
The proposed SQL would look something like this:
SELECT (list of fields) FROM aTable
WHERE CONVERT(VARCHAR(25), theColumn) LIKE '%2009%'
Here is part of the criteria that tries to emulate the call to convert:
Projections.SqlFunction("CONVERT",
NHibernateUtil.String,
Projections.Constant("varchar(25)"),
Projections.Property(searchCol))
The search column would be dynamically selected so it cannot be hard coded in a query.
The problem is that when the SQL is generated by nhibernate, its passing in the data type as a string, when there shouldn't be any quotes around it.
So the generated sql looks like:
(convert(#p3, this_.theColumn) LIKE #p4
When it needs to be:
(convert(varchar(25), this_.theColumn) LIKE #p4
I am definitely sure the problem is with Projections.Constant("varchar(25)") but I do not know the correct projections syntax to make it work.
If you could accept the CAST instead of CONVERT (And I am almost sure that you can), then there is more straightforward solution.
Instead of calling "SQL Server related" function, let's call the abstraction, which should be working on most DB Servers (based on supported NHibernate dilacts)
Projections.Cast(NHibernateUtil.String, Projections.Property(searchCol))
So the Restriction used in a WHERE clause could look like this:
Restrictions
.Like (
Projections.Cast(NHibernateUtil.String, Projections.Property(searchCol))
, "2009"
, MatchMode.Anywhere
)
And the result generated by NHibernate, using the SQL Server dialect would be:
WHERE cast( this_.theColumn as NVARCHAR(255)) like #p1 ... #p1=N'%2009%'
i have the SQL Query in a string and am executing using the Traditional way of using DataAdapter.
Am trying to add pagination to the Existing logic. how do i add Skip take to the SQL string.
I know of using Skip and other linq methods for LINQ Queries. But is it possible to use for a SQL query in a string format.
If yes how do i do it without adding RowNum to the query rather use skip and take.
Eg :
String sqlQuery = Select * from tablename ;
SqlDataAdapter com = new SqlDataAdapter(sqlQuery, Connection);
How do i use Linq methods on this SQL query for pagination rather going for ROWNUM
*Am not sure if am repeating the Question but i was not able to identify with the keywords
Thanks
How do i use Linq methods on this SQL query for pagination rather going for ROWNUM
You can't. You're issuing direct SQL - LINQ isn't involved here. LINQ will translate a query written in C# into SQL, but you can't start adding bits of LINQ to an existing SQL query. You should decide whether you actually want to write SQL, or whether you want to use LINQ. Then do just one at a time.
(You can use both in the same project, sure - but for a single query, you can't mix and match.)
Is there a way to see final query which is passed to SQL Server database from my C# app ?
For ex I got query:
SELECT * FROM mytable WHERE x = #yyyy;
This creates and SQLCommand object
SqlCommand cmd = new SqlCommand("SELECT * FROM mytable WHERE x = #yyyy");
Plus I need to pass parameter:
cmd.Parameters.Add("#yyyy","MyValue");
What I want to see (in debug in C# or somewhere in SQL Server Management Studio) is this:
SELECT * FROM mytable WHERE x = MyValue
Where can I find such query ?!
Best regards
Where can I find such query ?!
You can't. Such a query never exists. The values are not substituted into the SQL.
I think actually sp_executesql is called, and this function accepts the parameters separately from the SQL. You can check this using SQL Profiler to see the actual SQL.
Update:
ORDER BY #descOrAsc
Your problem is that parameters can only be used in certain places where expressions are allowed. DESC is not an expression - it is a reserved word. You cannot use a parameter containing the string "DESC" instead of writing the keyword DESC in the query.
Also, you haven't specified which column to order by.
You can run the SQL Server Profiler and see all the queries that get executed, to see whats happening (and copy paste these into the Sql Server Management Studio to do tests etc)
I would expect the query to be passed to SQL Server with the parameters. There should be no need for anything to ever create a full SQL-only query. It makes no sense to do so, as it just means more conversions for either the client, the server or both. On the server side, the query processor is going to want to parse the query into clauses with values - if the command can pass those values directly, where's the advantage on converting them into the SQL statement, only to have the server parse them into separate values again?
1.You can use SQL Profiler. (here you can see all process)
2.You can write all your queries to SQL Server table. And then you can always get queries from this table.
I'm trying to load data from oracle to sql server (Sorry for not writing this before)
I have a table(actually a view which has data from different tables) with 1 million records atleast. I designed my package in such a way that i have functions for business logics and call them in select query directly.
Ex:
X1(id varchar2)
x2(id varchar2, d1 date)
x3(id varchar2, d2 date)
Select id, x, y, z, decode (.....), x1(id), x2(id), x3(id)
FROM Table1
Note: My table has 20 columns and i call 5 different functions on atleast 6-7 columns.
And some functions compare the parameters passed with audit table and perform logic
How can i improve performance of my query or is there a better way to do this
I tried doing it in C# code but initial select of records is large enough for dataset and i get outofmemory exception.
my function does selects and then performs logic for example:
Function(c_x2, eid)
Select col1
into p_x1
from tableP
where eid = eid;
IF (p_x1 = NULL) THEN
ret_var := 'INITIAL';
ELSIF (p_x1 = 'L') AND (c_x2 = 'A') THEN
ret_var:= 'RL';
INSERT INTO Audit
(old_val, new_val, audit_event, id, pname)
VALUES
(p_x1, c_x2, 'RL', eid, 'PackageProcName');
ELSIF (p_x1 = 'A') AND (c_x2 = 'L') THEN
ret_var := 'GL';
INSERT INTO Audit
(old_val, new_val, audit_event, id, pname)
VALUES
(p_x1, c_x2, 'GL', eid, 'PackgProcName');
END IF;
RETURN ret_var;
i'm getting each row and performing
logic in C# and then inserting
If possible INSERT from the SELECT:
INSERT INTO YourNewTable
(col1, col2, col3)
SELECT
col1, col2, col3
FROM YourOldTable
WHERE ....
this will run significantly faster than a single query where you then loop over the result set and have an INSERT for each row.
EDIT as for the OP question edit:
you should be able to replace the function call to plain SQL in your query. Mimic the "initial" using a LEFT JOIN tableP, and the "RL" or "GL" can be calculated using CASE.
EDIT based on OP recent comments:
since you are loading data from Oracle into SQL Server, this is what I would do: most people that could help have moved on and will not read this question again, so open a new question where you say: 1) you need to load data from Oracle (version) to SQL Server Version 2) currently you are loading it from one query processing each row in C# and inserting it into SQL Server, and it is slow. and all the other details. There are much better ways of bulk loading data into SQL Server. As for this question, you could accept an answer, answer yourself where you explain you need to ask a new question, or just leave it unaccepted.
My recommendation is that you do not use functions and then call them within other SELECT statements. This:
SELECT t.id, ...
x1(t.id) ...
FROM TABLE t
...is equivalent to:
SELECT t.id, ...
(SELECT x.column FROM x1 x WHERE x.id = t.id)
FROM TABLE t
Encapsulation doesn't work in SQL like when using C#/etc. While the approach makes maintenance easier, performance suffers because sub selects will execute for every row returned.
A better approach would be to update the supporting function to include the join criteria (IE: "where x.id = t.id" for lack of real one) in the SELECT:
SELECT x.id
x.column
FROM x1 x
...so you can use it as a JOIN:
SELECT t.id, ...
x1.column
FROM TABLE t
JOIN (SELECT x.id,
x.column
FROM MY_PACKAGE.x) x1 ON x1.id = t.id
I prefer that to having to incorporate the function logic into the queries for sake of maintenance, but sometimes it can't be helped.
Personally I'd create an SSIS import to do this task. USing abulk insert you can imporve speed dramitcally and SSIS can handle the functions part after the bulk insert.
Firstly you need to find where the performance problem actually is. Then you can look at trying to solve it.
What is the performance of the view like? How long does it take the view to execute
without any of the function calls? Try running the command
How well does it perform? Does it take 1 minute or 1 hour?
create table the_view_table
as
select *
from the_view;
How well do the functions perform? According to the description you are making approximately 5 million function calls. They had better be pretty efficient! Also are the functions defined as deterministic. If the functions are defined using the deterministic keyword, the Oracle has a chance of optimizing away some of the calls.
Is there a way of reducing the number of function calls? The function are being called once the view has been evaluated and the million rows of data are available. BUT are all the input values from the highest level of the query? Can the function calls be imbeded into the view at a lower level. Consider the following two queries. Which would be quicker?
select
f.dim_id,
d.dim_col_1,
long_slow_function(d.dim_col_2) as dim_col_2
from large_fact_table f
join small_dim_table d on (f.dim_id = d.dim_id)
select
f.dim_id,
d.dim_col_1,
d.dim_col_2
from large_fact_table f
join (
select
dim_id,
dim_col_1,
long_slow_function(d.dim_col_2) as dim_col_2
from small_dim_table) d on (f.dim_id = d.dim_id)
Ideally the second query should run quicker as it calling the function fewer times.
The performance issue could be in any of these places and until you investigate the issue, it would be difficult to know where to direct your tuning efforts.
A couple of tips:
Don't load all records into RAM but process them one by one.
Try to run as many functions on the client as possible. Databases are really slow to execute user defined functions.
If you need to join two tables, it's sometimes possible to create two connections on the client. Fetch the data main data with connection 1 and the audit data with connection 2. Order the data for both connections in the same way so you can read single records from both connections and perform whatever you need on them.
If your functions always return the same result for the same input, use a computed column or a materialized view. The database will run the function once and save it in a table somewhere. That will make INSERT slow but SELECT quick.
Create a sorted intex on your table.
Introduction to SQL Server Indizes, other RDBMS are similar.
Edit since you edited your question:
Using a view is even more sub-optimal, especially when querying single rows from it. I think your "busines functions" are actually something like stored procedures?
As others suggested, in SQL always go set based. I assumed you already did that, hence my tip to start using indexing.