SQLite accessed by code has no tables? - sqlite

I created a SQLite database via SQLiteManager. I have a table called Envelopes, and other tables. When I access it from code (below) I get an exception saying that the table I'm trying to access doesn't exist. I've tried both Envelopes and ZVDB.Envelopes, and yes I've double checked my spelling of table names.
var conn = new SqliteConnection("Data Source=ZVDB");
using ( var cmd = conn.CreateCommand()) {
conn.Open();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "insert into Envelopes (Name, Remainder, Budget) values (#1, #2, #3); select ##identity";
cmd.Parameters.Add("#1", DbType.String).Value = env.Name;
cmd.Parameters.Add("#2", DbType.Int32).Value = env.Remainder;
cmd.Parameters.Add("#3", DbType.Int32).Value = env.Budget;
env.ID = (int) cmd.ExecuteScalar();
}
I have it in my MonoDevelop project, set with the proper action.

This means the path to the database is wrong.
In SQLite when you open a database that doesn't exist, by default it will just create a blank new one. No error.
When you then try to read or write to a table that doesn't exist, you get the error you described.
In the connection string you specified simply ZVDB with no path. Try specifying a full absolute path.

Samuel's answer is correct - if you want to access the database you need to ensure that you've included the database in your solution, set the 'build action' to "Content" and set 'Copt to output directory' to "Always copy".

Related

Azure Elastic Scale Sharding Key

I am moving my datamodel to Azure Elastic Scale.
After some testing and some experiences I fall in love if it, it is simple and with that kind of approach the code remains clean and easy to maintain.
I just have one big question, where is the Sharding key defined? I cannot find info on the sample downloaded from Visual Studio and I can beat that this is a straight forward answer.
In the sample offered by Microsoft the default sharding key is CustomerId but i cannot find where the reference to that key takes place.
Could it be in ShardMapName from configuration file?
Thanks in advance.
There is no explicit link between the the sharding key in the SQL schema and its usage (in code).
So in the Getting Started sample, the Customers and Orders table both contain a CustomerId column, and you can see that in DataDependentRoutingSample.cs when we access these tables we make sure to provide the same customerId value to the shardMap.OpenConnectionForKey method that we then use for customerId column (both in the SELECT and INSERT statements) in the following query.
// Looks up the key in the shard map and opens a connection to the shard
using (SqlConnection conn = shardMap.OpenConnectionForKey(customerId, credentialsConnectionString))
{
// Create a simple command that will insert or update the customer information
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = #"
IF EXISTS (SELECT 1 FROM Customers WHERE CustomerId = #customerId)
UPDATE Customers
SET Name = #name, RegionId = #regionId
WHERE CustomerId = #customerId
ELSE
INSERT INTO Customers (CustomerId, Name, RegionId)
VALUES (#customerId, #name, #regionId)";
cmd.Parameters.AddWithValue("#customerId", customerId);
cmd.Parameters.AddWithValue("#name", name);
cmd.Parameters.AddWithValue("#regionId", regionId);
cmd.CommandTimeout = 60;
// Execute the command
cmd.ExecuteNonQuery();
}
In other words, when you provide a certain key value in the OpenConnectionForKey call, it's your responsibility to make sure that all SQL queries with that connection are restricted to that key value, otherwise you may end up with incorrect results (e.g. if it was a SELECT query) or rows living on the wrong shard (e.g. if it was an INSERT query).
It's possible to fix this safety issue by using the new Row-Level Security feature. We have a sample called Entity Framework Multi-Tenant Shards that demonstrates how to combine Shard Maps with Row-Level Security. The relevant code is in ElasticScaleContext.cs:
SqlConnection conn = null;
try
{
// Ask shard map to broker a validated connection for the given key
conn = shardMap.OpenConnectionForKey(shardingKey, connectionStr, ConnectionOptions.Validate);
// Set CONTEXT_INFO to shardingKey to enable Row-Level Security filtering
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = #"SET CONTEXT_INFO #shardingKey";
cmd.Parameters.AddWithValue("#shardingKey", shardingKey);
cmd.ExecuteNonQuery();
return conn;
}
catch (Exception)
{
if (conn != null)
{
conn.Dispose();
}
throw;
}
Thanks for your great question!

SQL Server primary key error

I am designing a web-based logistics system using ASP.NET and SQL Server.
In one of my classes when I try to insert data to database, there is a violation of primary key error, but data inserts successfully into the table. I can not find out where the problem is. Can anyone see what I am doing wrong?
public int fillShipmentDetail()
{
int success = 0;
string connectionString = ConfigurationManager.ConnectionStrings["LGDB"].ToString();
SqlConnection sqlCon = new SqlConnection(connectionString);
SqlCommand sqlCom = new SqlCommand("fillShipmentDetails", sqlCon);
sqlCom.CommandType = CommandType.StoredProcedure;
sqlCon.Open();
sqlCom.Parameters.AddWithValue("shipOrderID", ShipOrderID);
sqlCom.Parameters.AddWithValue("totalWeight", TotalWeight);
sqlCom.Parameters.AddWithValue("weightIsMetric", WeightUnit);
sqlCom.Parameters.AddWithValue("weightIsImperial", VolumeUnit);
sqlCom.Parameters.AddWithValue("volume", Volume);
sqlCom.Parameters.AddWithValue("quantity", Quantity);
sqlCom.Parameters.AddWithValue("value", Value);
sqlCom.Parameters.AddWithValue("description", GoodsDescription);
success = sqlCom.ExecuteNonQuery();
if (success == 1)
{
success = 1;
}
else
{
success = 0;
}
sqlCon.Close();
return success;
}
aspx.cs page
Classes.ShipmentDetails fillShipmentDetails = new Classes.ShipmentDetails(
getLastShipOrder, _weight, _checkMetricImperial_weight, _checkMetricImperial_volume,
_volume, _quantity, _value, txtGoodsDescription.Text);
int success3 = fillShipmentDetails.fillShipmentDetail();
As you can see in the below picture the record shipOrderID 7192 is already inserted into the table.
I have deleted all three tables , and insert new data. although data inserts successfully but error happens again.
this screenshot shows everything clearly , by every new insertion into database there is a primary key error on last table , as you can see there is not any duplicate key and data inserted successfully.
looks like fillShipmentDetails.fillShipmentDetail() is getting fired twice. Put a Breakpoint in the code and check
shipOrderId already exists in your table.
You need to give it a new unique value. The reason why the table updates is because the shipOrderId already exists, so you can create a new Shipping Order with the Id, however that order is not referring to the correct shipOrderId

ASP.NET page can Insert a date to an Access database, but not Update

I have an ASP.NET page that needs to push a little data to an MS Access 2003 database. The process requires a Select on one record, Inserting one new record and Updating one record. I am connecting to the Access database via an OleDbConnection connection. So far, the Select and Insert functions are working exactly as expected (so I know my connection is good). The Update, however, fails to update any rows. The function to update the record looks like this:
public static int UpdateDeviceDates(int deviceId, DateTime nextTestDate)
{
var conn = DbConnect.AccessConnection();
var sqlString = WebConfigurationManager.AppSettings["UpdateDeviceDates"];
using (var cmd = new OleDbCommand(sqlString, conn))
{
cmd.Parameters.AddWithValue("#DeviceID", deviceId);
cmd.Parameters.AddWithValue("#NextTestDate", nextTestDate);
cmd.CommandType = CommandType.Text;
conn.Open();
var result = cmd.ExecuteNonQuery();
return result;
}
}
The sqlString pulled back from the web.config file looks like this:
UPDATE tblDevice
SET tblDevice.NextTestDate = #nextTestDate,
tblDevice.FirstNoticeDate = Null,
tblDevice.SecondNoticeDate = Null
WHERE DeviceID=#deviceId;
This query works fine if you paste it into a new Access query window and hit run, so I know the syntax is correct. I have done quite a bit of testing and figured out that it is the #nextTestDate field that is causing it to fail. When I took that out of the SQL string, it updated the record as expected. This is disconcerting, because the date I pass through to the Insert function works just fine.
I have looked around quite a bit and the closest I found to an answer was "Can't update date in aspx to a MS-ACCESS table". The main answer there was to change the parameter to a ShortDateString. I tried that to no effect. It was also suggested to bracket the date in #, since that is what Access does in its own queries. Unfortunately, that didn't work either.
I don't know why either of these should have been necessary, because the date comes through in exactly the same format as in the Insert statement and that works fine. I'm at my wits end here because the only thing I've found to make that query work is to remove the date parameter (which would defeat the main purpose of the query).
In your query, the parameters are in a different order, the order must match:
cmd.Parameters.AddWithValue("#NextTestDate", nextTestDate);
cmd.Parameters.AddWithValue("#DeviceID", deviceId);
To match:
UPDATE tblDevice
SET tblDevice.NextTestDate = #nextTestDate, <--- Param 1
tblDevice.FirstNoticeDate = Null,
tblDevice.SecondNoticeDate = Null
WHERE DeviceID=#deviceId; <--- Param 2

DataTableMapping using adapter.FillSchema method applied on a Stored Procedure

this is a method i was reading about #MSDN ,
my question is if for an example i would like to use it on a stored procedure
with the fact that the query of that stored procedure is already specifying columns to select from the table like following :
SELECT Columnsome, columnother, , , , ...FROM thisSQLdbTable
though i would like to implement the approach of that specific method , it seems very advanced from a little research i have made on
"the best way" available to extract data from SQL Server into Asp.net DataTable.
public static DataTable GetCustomerData(string dataSetName,
string connectionString)
{
DataTable table = new DataTable(dataSetName);
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT CustomerID, CompanyName, ContactName FROM dbo.Customers", connection);
DataTableMapping mapping = adapter.TableMappings.Add("Table", "Customers");
mapping.ColumnMappings.Add("CompanyName", "Name");
mapping.ColumnMappings.Add("ContactName", "Contact");
connection.Open();
adapter.FillSchema(table, SchemaType.Mapped);
adapter.Fill(table);
return table;
}
}
or is it not the method to use if i am querying via SP that specifies the selected column
i could actually drop that stored procedure if it is not requiered to select /specify columns
the stored procedure is doing a specific calculation and updates the table with results of calculation then i am switching it's "MODE" to select results from the table that was updated.
what i did is recyceling (; giving it a parameter (bit type)
stored procedure then asks for the value of supplied bool / bit Parameter,
if its is status true it updates (doing its original task it was made for)
if its false its doing a select oporation so i am using it as i would with 2 separated commands
but now that i have search for a better way to extract data from db into a Data table
i give up on the two way SP and i will make a selection via the exaple above if they're not intended to be used thogether as with my current SP that does preselection when servs the GetCustomersData() above.
So the question is do i need to let the function to make the selection or can i serve it with my sp ready made selection to implemet it with GetCustomersData() in the way that it will only do rest of task and only mapp the columns that was preselected
Still a bit confused on your actual requirement but here goes:
I See you are using a direct query in your C# code, 'best way' would be to make a SP out of it then say:
SqlCommand command = conn.CreateCommand();
SqlDataAdapter sqlAdapter = new SqlDataAdapter(command);
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "sp_GetCustomerData";
Then after you have added parameters if needed do:
conn.Open();
sqlAdapter.Fill(dtResult);
conn.Close();
Where dtResult is Datatable.
So you do not need to do any mapping in this case, and since you are using a SP from the Database it will work faster than your direct query and you can change the query logic any time without the need of re deploying your code.
Stored procedures are perfectly valid in this use case. however, if you want more of a properly mapped table, you have several options, some of which go beyond the use of DataTables.
You can use strongly typed DataSets or perhaps use an ORM (object relational mapper).
ref: Typed Datasets: http://msdn.microsoft.com/en-us/library/esbykkzb(v=vs.71).aspx
ref: What is an ORM : http://en.wikipedia.org/wiki/Object-relational_mapping
EXAMPLES OF ORM'S
ref: Entity Framework : http://msdn.microsoft.com/en-us/data/ef.aspx
ref: NHibernate: http://nhforge.org/

SQLite Parameters - Not allowing tablename as parameter

I'm developing an application in AIR via Flex, but I'm not seeing where I'm going wrong with SQLite (I'm used to MySQL). Parameters work, but only in certain instances. Is this part of the built-in sanitation system against sql injection? Thanks for any help!
Works:
sqlite
"INSERT :Fields FROM Category", where the parameter is :Fields = "*"
as3
var statement:SQLStatement = new SQLStatement();
statement.connection = connection;
statement.text = "INSERT :Fields FROM Category";
statement.parameters[":Fields"] = "*";
statement.execute;
Doesn't Work (SQL syntax error at ":Table"):
sqlite
"INSERT :Fields FROM :Table", where the parameters are :Fields = "*" and :Table = "Category"
as3
var statement:SQLStatement = new SQLStatement();
statement.connection = connection;
statement.text = "INSERT :Fields FROM :Table";
statement.parameters[":Fields"] = "*";
statement.parameters[":Table"] = "Category";
statement.execute;
Generally one cannot use SQL parameters/placeholders for database identifiers (tables, columns, views, schemas, etc.) or database functions (e.g., CURRENT_DATE), but instead only for binding literal values.
With server-side support for parameterized (a.k.a. prepared) statements, the DB engine parses your query once, remembering out the peculiars of any parameters -- their types, max lengths, precisions, etc. -- that you will bind in subsequent executions of the already-parsed query. But the query cannot be properly parsed into its syntactic elements if critical bits, like database objects, are unknown.
So, one generally has to substitute table names oneself, in a stored procedure or in client code which dynamically concats/interpolates/whatevers the SQL statement to be properly executed. In any case, please remember to use your SQL API's function for quoting database identifiers, since the API won't do it for you.
Not sure if this is the same but I ran across something similar in Java. Basically you can't add a table as a parameter so you must generate the statement like so:
var statement:SQLStatement = new SQLStatement();
statement.connection = connection;
statement.text = stringUtil.substitute("INSERT :Fields FROM {0}", "Category");
statement.parameters[":Fields"] = "*";
statement.execute;
This is mostly likely not the securest solution, so you might want to some custom validation of the data before you add the table name.. so someone doesn't try to send it the table name ";drop tableName..."

Resources