There was an error parsing the query. How to resolve it? - c#

I want to run sql statement which I frist read from .sql file.
I'm getting this error:
{"There was an error parsing the query. [ Token line number = 13,Token line offset = 1,Token in error = ALTER ]"}
There is my sql statement in .sql file:
CREATE TABLE [Test]
(
[Id] INT NOT NULL IDENTITY (1,1),
[DatabaseVersion] NVARCHAR(20) NOT NULL,
[Autorun] BIT,
[CurrentCulture] NVARCHAR(10),
[MailNotificationEnabled] BIT,
[RefreshInterval] INT,
[ModifiedDate] DATETIME NOT NULL,
[schemat] NVARCHAR(255)
)
ALTER TABLE [Test] ADD CONSTRAINT [PK_Test] PRIMARY KEY ([Id])
UPDATE [AppConfig]
SET [DatabaseVersion] = '0.12'
Reading file:
string oldVersion = GetOldDatabaseVersion();
string sqlScript = "";
sqlScript = GetScriptFromAssembly(oldVersion,
ConfigurationSettings.ValidDatabaseVersion);
ExecuteNonQuery(CommandType.Text, sqlScript);
ExecuteNonQuery method:
public int ExecuteNonQuery(CommandType type, string sql)
{
using (SqlCeConnection connection = CreateConnection())
{
return ExecuteNonQuery(connection, type, sql);
}
}
private int ExecuteNonQuery(SqlCeConnection connection, CommandType type, string sql)
{
using (SqlCeCommand command = new SqlCeCommand())
{
command.Connection = connection;
command.CommandType = type;
command.CommandText = sql;
return command.ExecuteNonQuery();
}
}
I doesn't know how to resolve it. When I run script dirctly on db it works.

Solved:
string sqlScript = GetScriptFromAssembly(GetOldDatabaseVersion(), ConfigurationSettings.ValidDatabaseVersion);
string[] scripts = sqlScript.Split(new string[] { #"/*$$*/" }, StringSplitOptions.None);
foreach(var script in scripts)
ExecuteNonQuery(CommandType.Text, script);
Added delimiters to sql:
CREATE TABLE [Test]
(
[Id] INT NOT NULL IDENTITY (1,1),
[DatabaseVersion] NVARCHAR(20) NOT NULL,
[Autorun] BIT,
[CurrentCulture] NVARCHAR(10),
[MailNotificationEnabled] BIT,
[RefreshInterval] INT,
[ModifiedDate] DATETIME NOT NULL,
[schemat] NVARCHAR(255)
)
/*$$*/
ALTER TABLE [Test] ADD CONSTRAINT [PK_Test] PRIMARY KEY ([Id])
/*$$*/
UPDATE [AppConfig]
SET [DatabaseVersion] = '0.12'

You must run each statement as a seperate command, you can use code like the helper function to seperate into commands if you seperate each command with GO:
https://github.com/ErikEJ/SqlCeToolbox/blob/master/src/API/Repositories/ServerDBRepository.cs#L639
As you can see I am using SqlCommandReaderStreamed from the DbUp package to do this

Please use the Go keyword before the Alter the table

Related

Get error on insert date from code sqlite

I'm trying to insert this string 2021-02-22T16:11 into sqlite database. I use VARCHAR(20) to store this this string. When I execute sql query from SQLite studio everything is fine.
But when I run the same code from my ASP Net Core app, it throws an error:
code = Error (1), message = System.Data.SQLite.SQLiteException (0x800007BF):
SQL logic error unrecognized token: "22T16"
I've tried different data types for this column (TEXT, STRING, DATETIME), but nothing works. Can't understand why it can't insert string even into VARCHAR column.
The function that invokes insert query:
public async Task<int> AssignTaskToUser(SaveTaskRequest req, int userId)
{
using (SQLiteConnection connection = new SQLiteConnection(_configuration.GetConnectionString("Default")))
{
long nextInvokeUnix = ((DateTimeOffset)DateTime.Parse(req.NextInvoke)).ToUnixTimeSeconds();
long intervalUnix = ((DateTimeOffset)DateTime.Parse(req.TimeInterval)).ToUnixTimeSeconds() +
(3600 * 24) * req.DaysInterval;
connection.Open();
SQLiteCommand command = new SQLiteCommand();
command.CommandText = $"INSERT INTO UserTasks " +
$"(Name, UserId, TaskId, NextInvokeString, NextInvokeUnix, DaysInterval, TimeInterval, IntervalUnix)" +
$"VALUES ({req.Name}, {userId}, {req.TaskId}, {req.NextInvoke}, {nextInvokeUnix}, {req.DaysInterval}, {req.TimeInterval}, {intervalUnix});" +
$"{getLastIdRequest}";
command.Connection = connection;
long userTaskId = (long)(await command.ExecuteScalarAsync());
foreach (var param in req.parameters)
{
command.CommandText = $"INSERT INTO UserTaskParameters " +
$"(UserTaskId, PrameterId, Value)" +
$"VALUES ({userTaskId}, {param.ParameterId}, {param.Value});";
await command.ExecuteScalarAsync();
}
return await GetChangesAsync(connection);
}
}
Table create script
CREATE TABLE UserTasks(
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name VARCHAR(30) NOT NULL,
UserId INTEGER NOT NULL,
TaskId INTEGER NOT NULL,
NextInvokeString VARCHAR(20),
NextInvokeUnix INTEGER,
DaysInterval INTEGER,
TimeInterval VARCHAR(6),
IntervalUnix INTEGER,
FOREIGN KEY (UserId)
REFERENCES Users (Id),
FOREIGN KEY (TaskID)
REFERENCES APITasks (Id)
);
Did you try to use this instead
2021-02-22T16:11:59
//or
2021-02-22T16:11:00
and maybe you can try this too:
$"VALUES ( '{req.Name}', {userId}, {req.TaskId}, '{req.NextInvoke}', {nextInvokeUnix}, ...

Inserting a ".01" into database c#

I am trying to insert "0000.0000.0000.0001" into a varchar(50) in my sql database in c#. I keep getting this error:
There was an error parsing the query. [ Token line number = 1,Token line offset = 122,Token in error = .0000 ]
How my insertion looks like is:
string version = "0000.0000.0000.0001";
INSERT INTO [DBFileInfo] (DBFileInfoID,DatabaseType,Version, Description, CreationDate,ReleaseDate)
values(1,1,"+version.ToString()+
",`Default Beverage DB created by DbGen`,
CURRENT_TIMESTAMP,CURRENT_TIMESTAMP)";
The initial build of the table is:
string info = " CREATE TABLE [DBFileInfo]( [DBFileInfoID] INT NOT NULL,[DatabaseType] INT NOT NULL DEFAULT(-1),[Version] VARCHAR(50) NOT NULL, [Description] NVARCHAR(256) NOT NULL, [CreationDate] DATETIME,[ReleaseDate] DATETIME);";
is there a way around this so I could insert the "." into it without getting an exception?
THanks!
You need to put the string inside single quotes:
string version = "0000.0000.0000.0001";
...values(1,1,'" + version + "','...
HOWEVER
I strongly recommend you use parameters instead. e.g.
string version = "0000.0000.0000.0001";
string sql = #"INSERT INTO [DBFileInfo] (DBFileInfoID,DatabaseType,Version, Description, CreationDate,ReleaseDate)
VALUES(1,1,#Version,'Default Beverage DB created by DbGen',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);";
using (var connection = new SqlConnection(yourConnectionString))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#Version", version);
connection.Open();
command.ExecuteNonQuery();
}
Probably you missed quotation marks, try:
... values(1,1,'"+version.ToString()+"','Default Beverage ..
Though you might be using parameter
... values(1,1,#version,'Default Beverage ..
in this case you will have to execute your statement with parameter #version and pass value to it.

Return Values from Dapper.net query with stored procedure

I am trying to call a stored procedure using Dapper.Net and get return values.
p.Add("#INCIDENT_ID", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
var retResults = con.Execute("usp_GetIncidentID", p, commandType:CommandType.StoredProcedure);
int IncidentID = p.Get<int>("INCIDENT_ID");
I have tried a couple of different things with the parameter direction and using the "#INCIDENT_ID". If you step through the results, you can see that the proper return values are coming down in the retResults value, but I am not able to access the values the way it is described in the documentation as below..
Stored Procedures
Dapper supports fully stored procs:
var user = cnn.Query<User>("spGetUser", new {Id = 1},
commandType: CommandType.StoredProcedure).First();}}}
If you want something more fancy, you can do:
var p = new DynamicParameters();
p.Add("#a", 11);
p.Add("#b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("#c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
cnn.Execute("spMagicProc", p, commandType: commandType.StoredProcedure);
int b = p.Get<int>("#b");
int c = p.Get<int>("#c");
I suspect (untested) that this is purely a mismatch in how you name the parameter; try (note the removed #):
p.Add("INCIDENT_ID", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
var retResults = con.Execute("usp_GetIncidentID", p, commandType:CommandType.StoredProcedure);
int IncidentID = p.Get<int>("INCIDENT_ID");
Using the test version of Dapper, I found this works like a charm:
result = dbConnection.ExecuteScalar<int>(typeof(UCCCCException).Name + "_c",
obj, commandType: CommandType.StoredProcedure);
I am writing a generic for use in inserting objects of any type into a database.
The stored procedure looks like this:
ALTER PROCEDURE [dbo].[UCCCCException_c]
(
#Id int = null,
#ExceptionDate datetime = null,
#HResult int = 0,
#Message varchar(8000) = null,
#Source varchar(8000) = null,
#StackTrace varchar(8000) = null,
#Module varchar(8000) = null,
#Name varchar(8000) = null,
#created_at datetime = null,
#updated_at datetime = null,
#created_by int = null,
#updated_by int = null
,
#Creator varchar(255) = null,
#Updator varchar(255) = null
)
AS
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Insert into dbo.uccccexceptions ( ExceptionDate, HResult, [Message], [Source], StackTrace, Module, Name)
values (
coalesce(#ExceptionDate,getdate()),
#HResult,
#Message,
#Source,
#StackTrace,
#Module,
#Name
)
;
select ##Identity;
go
The caveats on this are that you must specify an entry for every property in the class you are using, even if those properties do not exist in the target table, as a parameter for the stored procedure. This can be annoying if you have a number of fields which are view fields in MVC situations.
To get the return value, you just have to use Execute, and make sure your last statement is Select ##Identity in the stored procedure.
It works perfectly, and allows me to write a generic insert command in my repository like this:
public virtual int Insert(T obj)
{
int result = -2;
if (!databaseOnline)
{
throw new Exception(HttpStatusCode.ServiceUnavailable.ToString());
}
if (obj != null)
{
try
{
using (IDbConnection dbConnection = ConnectionProvider.OpenConnection())
{
dbConnection.Open();
result = dbConnection.ExecuteScalar<int>(typeof(T).Name + "_c",
obj, commandType: CommandType.StoredProcedure);
}
}
catch (SqlException sqlex)
{
Logger.LogError(sqlex, false);
throw;
}
catch (Exception ex)
{
Logger.LogError(ex);
throw;
}
}
return result;
}
I use the convention in my database that the name of the stored procedure is the type name followed by "_s" for select, "_c" for insert, "_d" for delete and "_u" for update.
PS: I hate using Dapper's DynamicParameters or any other device that requires you to use a different insert or update method for each of your classes in a generic repository.
You can read the value as below
var incidentId = retResults.ToList()[0].INCIDENT_ID;
I ran into a similar problem reading the results of a QueryMultiple. The first call to Read() returned the correct type, the second returned a DapperRow. I found that using the typed version of Read():
var lineExists = query.Read<int?>().FirstOrDefault() == 1;
solved my problem.
I've pared this down for simplicity. I'm using output parameters because that gives me full control of the datatype that is passed back. I could use this approach with any other scenario, not just inserts.
Stored Proc:
ALTER PROCEDURE User_Insert (
#EmailAddress nvarchar(255),
#Id bigint OUT
) AS
INSERT INTO User (
[EmailAddress]
) VALUES (
#EmailAddress
)
set #Id = SCOPE_IDENTITY()
Respository Code:
var sql = "Execute User_Insert #EmailAddress, #Id = #Id OUTPUT";
var _params = new DynamicParameters();
_params.Add("EmailAddress", user.EmailAddress);
_params.Add("Id", dbType: DbType.Int64, direction: ParameterDirection.Output);
using (var connection = new SqlConnection(ConnectionString)) {
connection.Open();
using (var transaction = connection.BeginTransaction()) {
var result = SqlMapper.Execute(connection, sql, param, transaction);
transaction.Commit();
}
}
var id = _params.Get<long>("Id");
The DynamicParameters solution is not clean to me. It is much better to make the stored procedure code return an integer (Select 1;) and use dapper ExecuteScalar<int>("[sp_name]", params);

Save multiple rows in one table in one connection IN sqlserver

Scenario: Just consider i have a table having 3 column Id, QuestionId and optedAnswer. I have a form which consists n no of question and some options for answer. On save button i want to save data in database(in my table).
Problem: I want to save all the answers in one connection.
Step taken by me: I made a string having structure questionId:optedAnswwer | questionId : optedAnswer | and so on....
I wrote a procedure. started a loop. split the data based on ':' and '|' and saved data in one connection. But it is a rigorous task. Is there any way to save the data directly without using loop and split.
Save your each questionId and its OptedAnswer in Datatable and then insert your datatable to SQL table as below :
DataTable dataTable = null; // your data needs to be here
try
{
ConnectionStringSettings mConString = ConfigurationManager.ConnectionStrings["SiteSqlServer"];
// Optional truncating old table
using (SqlConnection connection = new SqlConnection(mConString.ConnectionString))
{
connection.Open();
// Delete old entries
SqlCommand truncate = new SqlCommand("TRUNCATE TABLE MYTABLE", connection);
truncate.ExecuteNonQuery();
}
SqlBulkCopy bulkCopy = new SqlBulkCopy(mConString.ConnectionString, SqlBulkCopyOptions.TableLock)
{
DestinationTableName = "dbo.MYTABLE",
BatchSize = 100, //set your required size
BulkCopyTimeout = 360
};
bulkCopy.WriteToServer(dataTable);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Create a XML string of all your queastion and ans and pass these xml string to sql and use the
sp_xml_preparedocument procedure these sql inbuilt proc that reads the XML.
you can get more information on Bulk INsert
I would also go for an xml-centric solution, prepare you data in an xmldocument, post that inte the database and use a SELECT from the xml as source for your insert eg:
declare #xml XML
DECLARE #docid int
set #xml = N'<?xml version="1.0" ?>
<Custs>
<Cust>
<name>Erik</name>
<lastname>Stark</lastname>
</Cust>
<Cust>
<name>Donald</name>
<lastname>Duck</lastname>
</Cust>
<Cust>
<name>Johnny</name>
<lastname>Walker</lastname>
</Cust>
</Custs>'
EXEC sp_xml_preparedocument #docid OUTPUT, #xml
SELECT *
FROM OPENXML (#docid, '/Custs/Cust',2)
WITH (name varchar(50), lastname varchar(50))
exec sp_xml_removedocument #docid
There is another way to save multiple data in one connection.
Create a type of table like this
CREATE TYPE [dbo].[YourTypeName] AS TABLE(
[Col1] [bigint] NULL,
[Col2] [datetime] NULL,
[Col3] [bigint] NULL,
[Col4] [bigint] NULL,
[Col5] [datetime] NULL
)
and then write a procedure like this....
CREATE PROCEDURE [dbo].YOURPROCEDURENAME]
(
#yourDataTableName YourTypeName READONLY
)
AS
INSERT INTO TableName
(Col1,
Col2,
Col3,
Col4,
Col5)
SELECT CP.Val1,
CP.Val2,
CP.Val3,
CP.Val4,
CP.Val15)
FROM #yourDataTableName CP
GO
And then create a datatable in code behind and pass that datatable in prosedure like this...
SqlCommand cmd = new SqlCommand("YOURPROCEDURENAME");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#yourDataTableName", SqlDbType.Structured).Value = datatable;
cmd.Parameters[0].TypeName = "YourTypeName ";

"There was an error parsing the query. SQL Server CE

I wrote an little app in C# to keep track of customers and jobs but I get an error
"There was an error parsing the query.[Token line number = 1, Token
line offset = 14,Token in error = ']
I'm using a SQL Server CE .sdf database
public static void CreateEmployeeTable(string name)
{
conn.Open();
using (SqlCeCommand cmd = conn.CreateCommand())
{
cmd.CommandText = #"CREATE TABLE `#Name` (
`Id` INT(10) NOT NULL AUTO_INCREMENT,
`Job` VARCHAR(50) NULL,
`Pay` VARCHAR(50) NULL,
`TotalJobs` VARCHAR(50) NULL,
`TotalPay` VARCHAR(50) NULL,
PRIMARY KEY (`Id`)";
cmd.Parameters.AddWithValue("#Name", name);
cmd.ExecuteNonQuery();
}
}
I researched the error a lot and seems this error is pretty vague
You cannot parameterise a CREATE table statement that way.
Simply construct the CommandText string in code using string concatenation (being careful of possible SQL Injection vulnerabilities) and execute it.
You cannot parameterize the table name in your example. I altered your create table SQL to conform to supported data types for SQL CE. Please note that the NVARCHAR statements are set to a length of 100 to support up to the 50 characters you were specifying (VARCHAR is not supported).
I tested this code sample, but there are a couple more things to think about:
Your method is currently public. I don't know the context in which you are calling this, but consider making it private or internal.
Consider querying first to determine whether the table already exists to avoid an exception.
If at all possible I would create the connection in a using block directly above your command creation. That way you will know the connection gets closed and disposed. I'll leave that to your discretion.
public static void CreateEmployeeTable(string name)
{
const string createTableFormat = #"CREATE TABLE [{0}] (
Id INT IDENTITY NOT NULL PRIMARY KEY,
Job NVARCHAR(100) NULL,
Pay NVARCHAR(100) NULL,
TotalJobs NVARCHAR(100) NULL,
TotalPay NVARCHAR(100) NULL)";
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
// Just replace with your connection string.
using (SqlCeConnection cn = new SqlCeConnection(Settings.Default.LocalDbConnectionString))
using (SqlCeCommand cmd = cn.CreateCommand())
{
cmd.CommandText = string.Format(createTableFormat, name);
cn.Open();
cmd.ExecuteNonQuery()
}
}

Categories

Resources