SQL Server 2008 and EF7 (RC1) - Cannot Skip() and Take()? - sql-server-2008

I am aware that SQL Server 2012 and above has a new OFFSET syntax for pagination, which Entity Framework 7 seems to translate my LINQ to.
This explains why I'm getting the error Incorrect syntax near 'OFFSET'. Invalid usage of the option NEXT in the FETCH statement. because SQL Server 2008 doesn't recognize it.
In this question, someone answered that all we need to do, as of RC1 is to tack on .UseRowNumberForPaging() at Startup.cs's ConfigureServices().
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<MyDbContext>(options => {
options.UseSqlServer("someConnectionString").UseRowNumberForPaging();
});
This doesn't seem to work. I am still getting the same error. My guess is EF7 still compiles my LINQ to the new 2012+ SQL syntax. What to do?

You need to use SQL2012+ for use skip().take(), it doesn't work in sql2008.
For 2008 you can use:
select top 20 * from
(
select *,
ROW_NUMBER() OVER (ORDER BY columnid) AS ROW_NUM
from tablename
) x
where ROW_NUM>10

Your question seems to be have been cross-posted and solved at github.
The solution to this problem is, as stated by Arthur Vickers, to go to your project's Startup.cs and add UseRowNumberForPaging() to your db's options builder.
services.AddDbContext<ApplicationDbContext>(
options => {
options.UseSqlServer(
this.config.GetConnectionString("MyDatabaseConnectionString"),
builder => builder.UseRowNumberForPaging()
);
}
);
I tested this with .NET Core 2 and it works fine.

Related

Ebean ExpressionList.delete creating incorrect SQL?

My team recently upgraded to a newer version of Ebean (6.8.1) and I was trying out some of the new features. I saw that ExpressionList.delete is now available, but it doesn't work for me. Here's an example:
NewResponse.find.where().le("complete", startTime).delete();
When I run this command, I get a SQL syntax error:
delete from new_response t0 where t0.complete <= ?
I tested this out on my local database and that command (with the parameter filled in at the ? symbol) fails there, too. After doing some research, it seems an alias can't be used that way with a DELETE FROM (ex DELETE FROM `table` AS `alias` ... WHERE `alias`.`column` ... why syntax error?).
Is this a bug in Ebean? A limitation of my version of eBean/mySQL? Thanks.
I found that this bug was fixed in 7.2.1: https://github.com/ebean-orm/avaje-ebeanorm/issues/583

SSDT - CROSS APPLY OPENJSON

Trying to write a stored procedure in SSDT like below:
CREATE PROCEDURE Response.TransformHotel
#RequestIDs Request.RequestIDs READONLY
AS
BEGIN
INSERT INTO response.Hotel
SELECT EventID,
JSON_VALUE(x.[value], '$.Id') AS HotelID,
JSON_VALUE(x.[value], '$.HasSpecialOffer') AS HasSpecialOffer,
JSON_VALUE(x.[value], '$.HasClosedUserGroupSpecialOffer') AS HasClosedUserGroupSpecialOffer,
JSON_VALUE(x.[value], '$.ReviewSummary.AverageScore') AS AvarageScore,
JSON_VALUE(x.[value], '$.PercentageScore') AS PercentageScore,
JSON_VALUE(x.[value], '$.NumberOfReviews') AS NumberOfReviews
FROM Search.[Event] E
INNER JOIN #RequestIDs R ON R.RequestID = E.EventID
CROSS APPLY OPENJSON(E.MessageEvent, '$.Response.SearchResults') AS x
END
But it is giving me error "SQL46010: Incorrect Syntax near E."
However, if I write this on SSMS and execute it I get no issues.
I tried with another stored procedure and it seems OPENJSON is not available in SSDT.
CREATE PROCEDURE Request.TestOpenJSON
AS
SELECT * FROM
OPENJSON( (SELECT E.MessageEvent FROM search.Event E WHERE E.EventID = 1))
Visual Studio Profesional 2015
Version 14.0.25123.00 Update 2
.NET Framework Version 4.6.010555
Project Settings:
Target Platform: SQL Server 2016
Has anyone got any ideas? Rather not refactor the query to resolve a SSDT problem if possible.
I have used JSON VALUE and JSON QUERY throughout the project and not had any issues.
Ideas passed around is to add this as a post deploy script which also isn't great as it's a workaround rather than a solution.
Maybe too late to answer but I had the same problem with the openjson instruction when I found this post, so here my results. If you restore a database from Sql Server 2012 (for example, without support of openjson) into a Sql Server 2016, the compatibility level remains in Sql Server 2012. You have to upgrade the database (not the engine) to level 130 or better:
ALTER DATABASE database_name
SET COMPATIBILITY_LEVEL = 130
https://msdn.microsoft.com/es-es/library/bb510680.aspx

CakePHP 3 new ORM MySQL keyword errors [duplicate]

I'm using Cakephp 3 using sqlserver as datasource server. I am sure there's no problem with my database connection.. as home.ctp prompts that I am connected to my database.. and I'm as well using migrations plugin to create my tables.. it seems like there is no problem working with these tools. but after I bake my MVC, I only got page full of errors..
for example
$bin\cake bake all tests
there are no errors I found and MVC are in its specific folder, testController.php, testTable, etc.
and in browsers
localhost:8765\tests
but all I got is page of different errors.. Im seeing
Error: SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]Incorrect syntax near the keyword 'desc'.
SELECT * FROM (SELECT Tests.id AS [Tests__id], Tests.desc AS [Tests__desc], (ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS [_cake_page_rownum_] FROM tests Tests) _cake_paging_ WHERE _cake_paging_._cake_page_rownum_ <= :c0
and more errors on the left side.
I assume this is because of controllers with wrong queries or queries generated by bake is for mysql only. I just wanna know how to deal with this. is there a setting I forgot to do? please advice. I am new to Cakephp, and English is not my native language, sorry if I can't explain my question properly. thanks in advance.
As already mentioned by Vishal Gajjar in the comments, you are using the reserved keyword desc for your column name, hence the error, it's not bakes fault, it's yours.
In order to be able to use such reserved words, the column name needs to be quoted properly, however CakePHP 3 doesn't auto-quote by default anymore, as it's an expensive operation.
If you insist on using reserved words, enable identifier quoting via the quoteIdentifiers option in your app.php config, or enable it manually using the autoQuoting() (enableAutoQuoting() as of CakePHP 3.4) method of the DB driver.
See also
Cookbook > Database Access & ORM > Database Basics > Identifier Quoting
Cookbook > 3.x Migration Guide > New ORM Upgrade Guide > Identifier Quoting Disabled by Default
API > \Cake\Database\Driver::autoQuoting()
API > \Cake\Database\Driver::enableAutoQuoting()
You can use this code before problematic query:
$this->Tests->connection()->driver()->autoQuoting(true);
and when you are finished you can turn auto quoting off:
$this->Tests->connection()->driver()->autoQuoting(false);
So bad performance would be only on problematic query.
Use this :
SELECT * FROM (SELECT Tests.id AS [Tests__id], Tests.[desc] AS [Tests__desc],
(ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS [_cake_page_rownum_] FROM tests Tests) _cake_paging_
WHERE _cake_paging_._cake_page_rownum_ <= :c0
If you do use a keyword, use it in square braces [ ]

Entity Framework converts StartsWith to MySQL's Locate, MySQL's Locate doesn't use index

I'm using Entity Framework with MySQL, and my Linq Query:
db.Persons.Where(x => x.Surname.StartsWith("Zyw")).ToList();
..is producing the SQL:
SELECT PersonId, Forename, Surname
FROM Person
WHERE (LOCATE('Zyw', Surname)) = 1
...and it would seem that this doesn't make use of the index on Surname.
If LOCATE is replaced with the equivalent LIKE, the query speedily returns the required results. As it is it takes all afternoon.
Why is Entity Framework and its connecting drivers opting for this wierd LOCATE function / how can I make it use LIKE instead / why is MySQL making a poor index decision for the LOCATE function / how can I make it better?
Update:
I'm afraid I was guilty of over simplifying my code for this post, the Linq producing the error is in fact:
var target = "Zyw";
db.Persons.Where(x => x.Surname.StartsWith(target)).ToList();
If target term is hard coded, the SQL generated does indeed use LIKE, but with a variable term the SQL changes to use LOCATE.
This is all using the latest generally available MySQL for Windows as delivered by MySQL Installer 5.6.15.
Update:
A couple more notes to go with the bounty; am using:
Visual Studio 2010
EntityFramework 6.0.2
MySQL Installer 5.6.15,
which in turn gives:
MySql.Data 6.7.4
MySql.Data.Entities 6.7.4
The Entity Framework code is generated database first style.
I've also tried it with the latest connector from Nuget (MySql.Data 6.8.3) and the problem is still there.
It's likely your problem is caused by:
You are using an older connector with the bug.
You have a special case (using a variable to hold the .Contains search) described as a bug here
Does your case fall into any of those?
This looks like a regression of MySQL bug #64935 to me.
I can confirm that, using the same builds of EF6 and MySQL Connector, I'm getting the same SQL generated too:
context.stoppoints.Where(sp => sp.derivedName.StartsWith(stopName));
...logs as:
SELECT
`Extent1`.`primaryCode`,
...
`Extent1`.`stop_timezone`
FROM `stoppoints` AS `Extent1`
WHERE (LOCATE(#p__linq__0, `Extent1`.`derivedName`)) = 1
Entity Framework: 6.0.2
MySQL Connector.Net: 6.8.3
I have reported this as a MySQL bug regression.

Create View with Mutliple Tables in SQL Server 2008

I'm converting an app to use SQL Server 2008 that is currently using SQLite. How would I do the following view in SQL Server 2008? I can't seem to figure out the syntax for calling multiple tables:
CREATE VIEW new_mimetypes AS
SELECT
DISTINCT fd.mimetype AS 'newMimetype'
FROM
files_detail AS fd
WHERE
NOT EXISTS (
SELECT
m.mimetype
FROM
mimetypes AS m
WHERE
fd.mimetype = m.mimetype
)
[EDIT]
Nevermind. SQL Server Management Studio was complaining about syntax errors but it still took the SQL. That's what I get for thinking the IDE new what would work!
That syntax looks correct, are you getting an error?
I agree with #Adam Ruth that the syntax looks correct. I also wanted to add that you could use the "EXCEPT" operator as well to achieve the desired result:
CREATE VIEW [dbo].[new_mimetypes]
AS
SELECT mimetype As 'newMimetype' FROM files_detail
EXCEPT
SELECT mimetype FROM mimetypes