My application is using Entity Framework over a SQL Azure Database.
It has a feature that allows the the user to search for records based on a given phone number. The table being searched has many columns, including 3 columns for phone numbers: a BusinessPhone, a HomePhone and a CellPhone column. All three of these columns are indexed.
My EF DbContext is generating the following as part of the WHERE clause:
WHERE (10 = [Extent1].[Debtor_DebtorStatus]) AND
(((LOWER([Extent1].[BusinessPhone])) = (LOWER(N'012345678')))
OR ((LOWER([Extent1].[HomePhone])) = (LOWER(N'012345678')))
OR ((LOWER([Extent1].[CellPhone])) = (LOWER(N'012348678')))
)
The query is taking about 3 minutes to return a response (even when I run it in SQL Management Studio).
If I edit this SQL statement and remove the LOWER() function, then it executes in less than a second!!!
Is there some setting I can flick to make EntityFramework NOT use the LOWER() function in the generated SQL statement?
Of if that is not possible, is there a way I can intercept this SQL statement and remove the LOWER() functions in code before execution on the database?
Related
So I've got a SQL query that is called from an API that I'm trying to write an integration test for. I have the method that prepares the data totally working, but I realized that I don't know how to actually execute the query to check that data (and run the test). Here is what the query looks like (slightly redacted to protect confidental data):
SELECT HeaderQuery.[headerid],
kaq.[applicationname],
HeaderQuery.[usersession],
HeaderQuery.[username],
HeaderQuery.[referringurl],
HeaderQuery.[route],
HeaderQuery.[method],
HeaderQuery.[logdate],
HeaderQuery.[logtype],
HeaderQuery.[statuscode],
HeaderQuery.[statusdescription],
DetailQuery.[detailid],
DetailQuery.[name],
DetailQuery.[value]
FROM [DATABASE1].[dbo].[apilogheader] HeaderQuery
LEFT JOIN [DATABASE1].[dbo].[apilogdetails] DetailQuery
ON HeaderQuery.[headerid] = DetailQuery.[headerid]
INNER JOIN [DATABASE2].[dbo].[apps] kaq
ON HeaderQuery.[applicationid] = kaq.[applicationid]
WHERE HeaderQuery.[applicationid] = #applicationid1
AND HeaderQuery.[logdate] >= #logdate2
AND HeaderQuery.[logdate] <= #logdate3
For the sake of the test, and considering I already have the SQL script, I was hoping to be able to just execute that script above (providing the where clause programmatically) using context.Database.SqlQuery<string>(QUERY) but since I have two different contexts, I'm not sure how to do that.
The short answer is no, EF doesn’t support cross database queries. However there are a few things you can try.
You can use two different database contexts (one for each database).
Run your respective queries and then merge / massage the data after
the query returns.
Create a database view and query the view through EF.
Using a SYNONYM
https://rachel53461.wordpress.com/2011/05/22/tricking-ef-to-span-multiple-databases/
If the databases are on the same server, you can try using a
DbCommandInterceptor
I’ve had this requirement before and personally like the view option.
Calling .ToString() to a IQueryable will return the generated SQL query with the values of the variables not plugged in yet. So there are these p__linq__n with n=0, 1, 2... in the query itself.
eg: SELECT * FROM foo WHERE x = p__linq__0
Question: Is it possible to get the final query? with the values of these variables already plugged into the query?
eg: SELECT * FROM foo WHERE x = 6
EF parametrizes queries to avoid Sql injections attacks and to be able to cache and re-use the same query even if some values change. To see parameters you can use the logging feature introduced in EF6. See this blogpost series for more details.
I am trying to update a column (in an MS SQL table) which holds very long strings (text data type) appending it with a string from my application using JPQL. But the following query fails:
UPDATE entity e SET e.longText = CONCAT(e.longText, :textToAppend) WHERE e.id = :id
with message
The data types text and nvarchar are incompatible in the add operator.
The problem is that we need to also support other DBS than MS SQL database and DBS-specific queries are out of question (at least if there is another way).
With this query I was trying to bypass querying for the whole long text and concatenating it in the app and updating it back, so it's not slow (the query is called quite often).
Can I somehow append a string to a very long text column without doing it manually in the app and so it works in MS SQL? (I know there is no cast support in JPQL, sadly)
Using JPA with Hibernate.
It turned out I was using old hibernate dialect. There is a dialect for SQL Server 2008 (org.hibernate.dialect.SQLServer2008Dialect) which maps #Lob String properties correctly.
I have a generic code that is used to retrieve DDL information from a Firebird database (FB2.1). It generates SQL code like
SELECT * FROM MyTable where 'c' <> 'c'
I cannot change this code. Actually, if that matters, it is inside Report Builder 10.
The fact is that some tables from my database are becoming a litle too populated (>1M records) and that query is starting to take too long to execute.
If I try to execute
SELECT * FROM MyTable where SomeIndexedField = SomeImpossibleValue
it will obviously use that index and run very quickly.
Well, it wouldn´t be that hard to the database find out that that is an impossible matcher and make some sort of optimization and avoid testing it against each row.
Is there any way to make my firebird database to optimize that search?
As the filter condition is a negative proposition (and also doesn't refer a column to search, but only a value to compare to another value), Firebird need to do a full table scan (without use any index) to confirm that aren't any record that meet your criteria.
If you can't change you need to wait for the upcoming 3.0 version, that will implement the Boolean data type, and therefore should start to evaluate "constant" fake comparisons in advance (maybe the client library will do this evaluation before send the statement to the server?).
Let's say I have a SQL 2005 database with a table called Restaurants. The Restaurants table has the following columns:
RestaurantId
Name
Latitude
Longitude
I want to let users search for restaurants by name and/or address. How do I write the LINQ query to support this? I need to be able to support the possibility that the user doesn't enter in a name or address, just the name, just the address, or both name and address.
My initial idea was to write a stored procedure to calculate the distance between two lat/long pairs and a table value function for calling FREETEXTTABLE and using some conditional Join calls on my query. However, it appears that Entity Framework 4 doesn't support table value functions.
You certainly can write a proc which returns entity types. Indeed, in EF 1 that was the only option for procs. The proc returns a set of values, not a table, but I can't see that you actually need this.
You can also do free-form T-SQL in EF 4 using Context.ExecuteStoreQuery.
You cannot write any LINQ that supports geospatial queries at this point of time - be it EF or LinqToSql. This is because there is no LINQ syntax which can handle the special ST<whatever> spatial syntax that exists in SQL Server 2008. (eg. STIntersects(..))
You will need to write a Stored Procedure which you can then get access to via EF.
If you wish to return a Sql GEOGRAPHY field in a result, you will need to return a VARBINARY(MAX) i think as the equivalent field type for the C# code.
Hope This Helps.