insert query in vb2010 isn´t working - visual-studio-2010

i have this query that works nice to insert data in aaccess db, but now im trying to insert on a sqllite3 db but im having trouble using the same query
Imports System.Data.Odbc
Public Class Form1
Public con As New OdbcConnection("Dsn=SQLite3 Datasource;database=C:\Users\pcampos\Desktop\spiceworks_prod.db;stepapi=0;syncpragma=NORMAL;notxn=0;timeout=100000;shortnames=0;longnames=0;nocreat=0;nowchar=0;fksupport=0;oemcp=0;bigint=0")
Dim query As String = "INSERT INTO INSERT INTO tickets(id, summary, status) VALUES(#id,#summary,#status )"
con.Close()
con.Open()
Using cmd As New OdbcCommand(query, con)
cmd.Parameters.AddWithValue("#id", OdbcType.VarChar).Value = test
cmd.Parameters.AddWithValue("#sumamry", OdbcType.VarChar).Value = "ola ola ola"
cmd.Parameters.AddWithValue("#staus", OdbcType.VarChar).Value = "close"
Dim x As Integer = cmd.ExecuteNonQuery()
MsgBox(x)
If x < 1 Then
MessageBox.Show("Erro ao inserir", My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
MessageBox.Show("Registo1 inserido com sucesso!", My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Using
End Class

That query is not valid SQL. It should be something like this:
Dim query As String = "INSERT INTO tickets (id, summary, status) VALUES( #id, #summary, #status )"
See the SQLite Insert Query Manual for a diagram detailing the order of key words in an SQL Insert statement. The SQL would be an error on other SQL based systems, not just SQLite. Just thought I'd linke to that manual page as it is very useful.

Related

LINQ to SQL, Visual Basic - Listbox Receives the Query NOT the Result

Overview
This is a homework assignment using LINQ to SQL in a Visual Basic application. It is correct in most ways except that I have a partially broken result. Rather than adding the result of my second query to my listbox, my code adds a weird representation of the query itself. Below is a description of the DB, followed by my output (intended and actual), and finally my code. Please point me toward the broken concept so I can figure out what I am missing. Thanks much.
DB info
I am using two tables, called Members and Payments, from one DB. Members has a primary key called ID and also has the fields first_name and last_name. Payments has a foreign key called Members_Id, which is associated to the Member's primary key; Payments also has the payment values under the column Payments.
Output should be like this
Member name = John Smith
$48.00, 10/20/2005
$44.00, 3/11/2006
But is this instead
Member name = SELECT ([t0].[First_Name] + #p1) + [t0].[Last_Name]
AS [value]FROM[dbo].[Members] AS [t0].[ID] = #p0
$48.00, 10/20/2005
$44.00, 3/11/2006
My VB Code
Public Class FormPaymentsGroup
Private db As New KarateClassesDataContext
Private Sub FormPaymentsGroup_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.PaymentsTableAdapter.Fill(Me.KarateDataSet.Payments)
'Group payments by Member_ID (FKey) in the Payments table. (Working fine)
Dim IdQuery = From aMember In db.Payments
Group aMember By aMember.Member_Id
Into MemberPayments = Group
For Each memberID In IdQuery
' Use the passed member_Id to target the row in the Members table and return the first_name & last_name.
' PROBLEM: This only seems to be returning the query itself; not the result.
Dim currMemberID = memberID.Member_Id
Dim nameQuery = From aName In db.Members
Where aName.ID = currMemberID
Select aName.First_Name + " " + aName.Last_Name
Dim currName = nameQuery.ToString ' Load the query result into a portable variable.
LbxMemberPayments.Items.Add("Member name = " & currName) ' PROBLEM: This is where the name SHOULD BE posted to the listbox.
' This is bound to the Members table but directs it based on the above IdQuery.
For Each enteredPayment In memberID.MemberPayments
LbxMemberPayments.Items.Add(vbTab & FormatCurrency(enteredPayment.Amount) & ", " & enteredPayment.Payment_Date)
Next
LbxMemberPayments.Items.Add(vbCr) ' Carriage return formatting
Next
End Sub
End Class
change
Dim currName = nameQuery.ToString
to
Dim currName = nameQuery.FirstOrDefault

Using ruby sqlite to insert to table within a loop which is part of a method

I'm struggling to loop through an "INSERT INTO" sqlite statement within a Ruby method. Please advice. My code is shown below. The error messages seem to suggest that Ruby doesn't recognise the db object within the method?? Apologies for being a bit of a noob but I've trawled through the internet and I couldn't find the answer :(
require "sqlite3"
require "nokogiri"
begin
db = SQLite3::Database.new('RM.db')
db.execute "CREATE TABLE IF NOT EXISTS Properties(address TEXT, askingPrice TEXT)"
def get_property_list(newpage, dbname)
resultspage = Nokogiri::HTML(open(newpage))
details = resultspage.css("div.details.clearfix")
count_items = details.count
puts "there are #{count_items} items on this page"
for i in 0..count_items-1
address = resultspage.css("span.displayaddress")[i]
asking_price = resultspage.css("p.price")[i]
puts address.text
puts asking_price.text
dbname.execute "INSERT INTO Properties VALUES(#{address}, #{asking_price})"
end
end
get_property_list("someurl.com", db)
rows = db.execute("select * from Properties")
p rows
ensure
db.close if db
end
You're not quoting either value in your INSERT. You shouldn't be using string interpolation for SQL at all, use bound parameters and always specify the column names too:
dbname.execute 'INSERT INTO Properties (address, askingPrice) VALUES (?, ?)', address, asking_price
Or you could prepare a statement and use it over and over again:
insert = dbname.prepare('INSERT INTO Properties (address, askingPrice) VALUES (?, ?)')
for i in 0..count_items-1
#...
insert.execute(address, asking_price)
end

deleting a record in linq to sql (vb.net) what is wrong with my code?

I am getting the correct Employee Id in the VarEmpID variable. When I click on delete
It is giving me
Unable to cast object of type 'System.Data.Linq.DataQuery`1[my name space]' to type 'namespace'.
enter code here
Protected Sub radGrid1_DeleteCommand(ByVal source As Object, ByVal e As GridCommandEventArgs) Handles radGrid1.DeleteCommand
Dim VarEmpId As String = (CType(e.Item, GridDataItem)).OwnerTableView.DataKeyValues(e.Item.ItemIndex)("EmpId").ToString()
Using dc1 As New EmployeesDataClassesDataContext()
Dim EmployeeEntry = (From p In dc1.Employees
Where (p.EmpId = VarEmpId)
Select p)
dc1.Employees.DeleteOnSubmit(EmployeeEntry)
dc1.SubmitChanges()
Dim queryResults = (From queryItem In EmployeeEntry Select queryItem).ToList()
If queryResults.Any Then
radGrid1.DataSource = queryResults
radGrid1.DataBind()
End If
End Using
End Sub
dc1.Employees.DeleteOnSubmit(EmployeeEntry)
That method expects an Employee instance. Instead, you passed in an employee query.
Dim EmployeeEntry = ( query )
This is a query, not an entry. Consider calling Enumerable.First to get the first result of the query, and then deleting that.
Modified added Dim EmployeeEntry = (From p In dc1.Employees Where (p.EmpId = VarEmpId) Select p).singleorDefault() After that commented out the queryresults part and binded data again it solved my problem. – SmilingLily

Reading/Writing DataTables to and from an OleDb Database LINQ

My current project is to take information from an OleDbDatabase and .CSV files and place it all into a larger OleDbDatabase.
I have currently read in all the information I need from both .CSV files, and the OleDbDatabase into DataTables.... Where it is getting hairy is writing all of the information back to another OleDbDatabase.
Right now my current method is to do something like this:
OleDbTransaction myTransaction = null;
try
{
OleDbConnection conn = new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + Database);
conn.Open();
OleDbCommand command = conn.CreateCommand();
string strSQL;
command.Transaction = myTransaction;
strSQL = "Insert into TABLE " +
"(FirstName, LastName) values ('" +
FirstName + "', '" + LastName + "')";
command.CommandType = CommandType.Text;
command.CommandText = strSQL;
command.ExecuteNonQuery();
conn.close();
catch (Exception)
{
// IF invalid data is entered, rolls back the database
myTransaction.Rollback();
}
Of course, this is very basic and I'm using an SQL command to commit my transactions to a connection. My problem is I could do this, but I have about 200 fields that need inserted over several tables. I'm willing to do the leg work if that's the only way to go. But I feel like there is an easier method. Is there anything in LINQ that could help me out with this?
If the column names in the DataTable match exactly to the column names in the destination table, then you might be able to use a OleDbCommandBuilder (Warning: I haven't tested this yet). One area you may run into problems is if the data types of the source data table do not match those of the destination table (e.g if the source column data types are all strings).
EDIT
I revised my original code in a number of ways. First, I switched to using the Merge method on a DataTable. This allowed me to skip using the LoadDataRow in a loop.
using ( var conn = new OleDbConnection( destinationConnString ) )
{
//query off the destination table. Could also use Select Col1, Col2..
//if you were not going to insert into all columns.
const string selectSql = "Select * From [DestinationTable]";
using ( var adapter = new OleDbDataAdapter( selectSql, conn ) )
{
using ( var builder = new OleDbCommandBuilder( adapter ) )
{
conn.Open();
var destinationTable = new DataTable();
adapter.Fill( destinationTable );
//if the column names do not match exactly, then they
//will be skipped
destinationTable.Merge( sourceDataTable, true, MissingSchemaAction.Ignore );
//ensure that all rows are marked as Added.
destinationTable.AcceptChanges();
foreach ( DataRow row in destinationTable.Rows )
row.SetAdded();
builder.QuotePrefix = "[";
builder.QuoteSuffix= "]";
//forces the builder to rebuild its insert command
builder.GetInsertCommand();
adapter.Update( destinationTable );
}
}
}
ADDITION An alternate solution would be to use a framework like FileHelpers to read the CSV file and post it into your database. It does have an OleDbStorage DataLink for posting into OleDb sources. See the SqlServerStorage InsertRecord example to see how (in the end substitute OleDbStorage for SqlServerStorage).
It sounds like you have many .mdb and .csv that you need to merge into a single .mdb. This answer is running with that assumption, and that you have SQL Server available to you. If you don't, then consider downloading SQL Express.
Use SQL Server to act as the broker between your multiple datasources and your target datastore. Script each datasource as an insert into a SQL Server holding table. When all data is loaded into the holding table, perform a final push into your target Access datastore.
Consider these steps:
In SQL Server, create a holding table for the imported CSV data.
CREATE TABLE CsvImport
(CustomerID smallint,
LastName varchar(40),
BirthDate smalldatetime)
Create a stored proc whose job will be to read a given CSV filepath, and insert into a SQL Server table.
CREATE PROC ReadFromCSV
#CsvFilePath varchar(1000)
AS
BULK
INSERT CsvImport
FROM #CsvFilePath --'c:\some.csv'
WITH
(
FIELDTERMINATOR = ',', --your own specific terminators should go here
ROWTERMINATOR = '\n'
)
GO
Create a script to call this stored proc for each .csv file you have on disk. Perhaps some Excel trickery or filesystem dir piped commands can help you create these statements.
exec ReadFromCSV 'c:\1.csv
For each .mdb datasource, create a temp linked server.
DECLARE #MdbFilePath varchar(1000);
SELECT #MdbFilePath = 'C:\MyMdb1.mdb';
EXEC master.dbo.sp_addlinkedserver #server = N'MY_ACCESS_DB_', #srvproduct=N'Access', #provider=N'Microsoft.Jet.OLEDB.4.0', #datasrc=#MdbFilePath
-- grab the relevant data
--your data's now in the table...
INSERT CsvImport(CustomerID,
SELECT [CustomerID]
,[LastName]
,[BirthDate]
FROM [MY_ACCESS_DB_]...[Customers]
--remove the linked server
EXEC master.dbo.sp_dropserver #server=N'MY_ACCESS_DB_', #droplogins='droplogins'
When you're done importing data into that holding table, create a Linked Server in your SQL Server instance. This is the target datastore. SELECT the data from SQL Server into Access.
EXEC master.dbo.sp_addlinkedserver #server = N'MY_ACCESS_TARGET', #srvproduct=N'Access', #provider=N'Microsoft.Jet.OLEDB.4.0', #datasrc='C:\Target.mdb'
INSERT INTO [MY_ACCESS_TARGET]...[Customer]
([CustomerID]
,[LastName]
,[BirthDate])
SELECT Customer,
LastName,
BirthDate
FROM CsvImport

Linq Compiled Queries and int[] as parameter

I'm using the following LINQ to SQL compiled query.
private static Func<MyDataContext, int[], int> MainSearchQuery =
CompiledQuery.Compile((MyDataContext db, int[] online ) =>
(from u in db.Users where online.Contains(u.username)
select u));
I know it is not possible to use sequence input paramter for a compiled query and im getting “Parameters cannot be sequences” error when running it.
On another post here related , I saw that there is some solution but I couldn't understand it.
Does anyone know to use complied query with array as input paramter?
Please post example if you do.
Like the post that you referenced, it's not really possible out of the box. The post also references creating your own query provider, but it's a bit of overhead and complexity that you probably don't need.
You have a few options here:
Don't use a compiled query. Rather, have a method which will create a where clause from each item in the array resulting in something like this (psuedo-code):
where
online[0] == u.username ||
online[1] == u.username ||
...
online[n] == u.username
Note that you would have to use expression here to create each OR clause.
If you are using SQL Server 2008, create a scalar valued function which will take a table-valued parameter and a value to compare againt. It will return a bit (to indicate if the item is in the values in the table). Then expose that function through LINQ-to-SQL on your data context. From there, you should be able to create a CompiledQuery for that. Note that in this case, you should take an IEnumerable<string> (assuming username is of type string) instead of an array, just because you might have more than one way of representing a sequence of strings, and to SQL server for this operation, it won't matter what the order is.
One solution that I have found myself doing (for MS SQL 2005/2008). And I'm not sure if it is appropriate in all scenarios is to just write dynamic sql and execute it against the datacontext using the ExecuteQuery method.
For example, if I have an unbounded list that I am trying to pass to a query to do a contains...
' Mock a list of values
Dim ids as New List(of Integer)
ids.Add(1)
ids.Add(2)
' ....
ids.Add(1234)
Dim indivs = (From c In context.Individuals _
Where ids.Contains(c.Id) _
Select c).ToList
I would modify this query to create a SQL string to execute against the database directly like so...
Dim str As New Text.StringBuilder("")
Dim declareStmt as string = "declare #ids table (indivId int) " & vbcrlf)
For i As Integer = 0 To ids.Count - 1
str.Append("select " & ids(i).ToString() & " & vbcrlf)
If i < ids.Count Then
str.Append("union " & vbcrlf)
End If
Next
Dim selStatement As String = "select * From " & context.Mapping.GetTable(GetType(Individuals)).TableName & _
" indiv " & vbcrlf & _
" inner join #ids ids on indiv.id = ids.id"
Dim query = declareStmt & str.ToString & selStatement
Dim result = context.ExecuteQuery(of Individual)(query).ToList
So barring any syntax errors or bugs that I coded (the above is more or less psuedo code and not tested), the above will generate a table variable in SQL and execute an inner join against the desired table (Individuals in this example) and avoid the use of a "IN" statement.
Hope that helps someone out!

Resources