Logs file into a database - sql

So, I have an application where I am able to drop a file into a button and the information will be shown on my database. To make things better I am trying after add something a query will run with an INNER JOIN where there are 2 tables, one of them will simply save the files info and the other one will save the date and time of that added file. I already have the LogsFile method:
Private Sub LogFileAdicionados()
Dim LogsFile As String = My.Application.Info.DirectoryPath
Dim logtext As String = lblName.Text
Dim logtext2 As String = lblSize.Text
Dim vt As String = "The file " & logtext & " com " & logtext2 & " KB " & "was added at " & TimeOfDay & " in " & Date.Today & "." & vbCrLf
My.Computer.FileSystem.WriteAllText(LogsFile + "\LogsAdded.txt", vt, True)
End Sub
So what should I do to INSERT the data and time values onto the Logs table?

As Zaggler pointed out, you need at least to attempt to do it yourself in order to post more meaningful question. However I'm going to set you on the track and see what happen...
First you need an approach on how to interact with your database. I'll show you how to do it with ADO.NET data objects, but keep in mind that there are other tools/frameworks to interact with a DB storage.
Next you need the connection string to your database. You can find hundreds of examples here.
Then you can do some fun stuff, like:
Using conn As New SqlConnection("connection string to your DB goes here")
Using cmd = conn.CreateCommand()
cmd.CommandText = "INSERT INTO Logs (fields definition) VALUES" + vt
cmd.ExecuteNonQuery()
End Using
End Using
Basically this outlining saving data to a SQL DB, using ADO.NET data objects.

Related

How to add rows in an Access Table with parameters?

This is my function:
Function SQL_InsertUpdate(mySQLConnection As OleDbConnection, mySQLCommand As String, mySQLTable As String, mySQLTableColumns() As String, myParameters() As String)
Dim SQLCommand As OleDbCommand = New OleDbCommand(mySQLCommand, mySQLConnection)
Dim myStringConstruct = mySQLCommand & " " & mySQLTable & " ("
'==============
For Each item In mySQLTableColumns
myStringConstruct = myStringConstruct & item & ", "
Next
myStringConstruct = Strings.Left(myStringConstruct, Len(myStringConstruct) - 2)
myStringConstruct = myStringConstruct & ") VALUES ("
For i As Integer = 0 To mySQLTableColumns.Length - 1
myStringConstruct = myStringConstruct & "#" & mySQLTableColumns(i) & ", "
SQLCommand.Parameters.AddWithValue("#" & mySQLTableColumns(i), myParameters(i))
Next
myStringConstruct = Strings.Left(myStringConstruct, Len(myStringConstruct) - 2)
myStringConstruct = myStringConstruct & ")"
SQLCommand.ExecuteNonQuery()
End Function
This is how I call the function:
Dim myParameters() As String = ({myNewID.ToString, myUser.ToString, myDepartment.ToString, mySubsidiary.ToString, myTitle.ToString, myRecurrence.ToString, myImpact.ToString, myTimeSaved.ToString, myPriority.ToString, myStatus.ToString, myTechnology.ToString, myDeveloper.ToString, myCostSave.ToString, myDescription.ToString, myCommentary.ToString, myDateSubmitted.ToString, myDateModified.ToString, myInReviewDate.ToString, myManagerReviewDate.ToString, myDigitalReviewDate.ToString, myRejectedDate.ToString, myInProgressDate.ToString, myDevelopedDate.ToString, myImplementedDate.ToString})
Dim mySQLTableColumns() As String = ({"ID", "myUser", "myDepartment", "mySubsidiary", "myTitle", "myRecurrence", "myImpact", "myTimeSaved", "myPriority", "myStatus", "myTechnology", "myDeveloper", "myCostSave", "myDescription", "myCommentary", "myDateSubmitted", "myDateModified", "myInReviewDate", "myManagerReviewDate", "myDigitalReviewDate", "myRejectedDate", "myInProgressDate", "myDevelopedDate", "myImplementedDate"})
SQL_InsertUpdate(SQLConnection, "INSERT INTO", "SIMSBase", mySQLTableColumns, myParameters)
This is the constructed command string output:
INSERT INTO SIMSBase (ID, myUser, myDepartment, mySubsidiary, myTitle,
myRecurrence, myImpact, myTimeSaved, myPriority, myStatus,
myTechnology, myDeveloper, myCostSave, myDescription, myCommentary,
myDateSubmitted, myDateModified, myInReviewDate, myManagerReviewDate,
myDigitalReviewDate, myRejectedDate, myInProgressDate,
myDevelopedDate, myImplementedDate) VALUES (#ID, #myUser,
#myDepartment, #mySubsidiary, #myTitle, #myRecurrence, #myImpact,
#myTimeSaved, #myPriority, #myStatus, #myTechnology, #myDeveloper,
#myCostSave, #myDescription, #myCommentary, #myDateSubmitted,
#myDateModified, #myInReviewDate, #myManagerReviewDate,
#myDigitalReviewDate, #myRejectedDate, #myInProgressDate,
#myDevelopedDate, #myImplementedDate)
This is the error I receive:
$exception {"Syntax error in INSERT INTO statement."} System.Data.OleDb.OleDbException
Now I have no clue what syntax error I could have, I looked here for another person who has no issue in this Stack question: Insert data into SQL database in VB.NET, my syntax is similar.
I don't know what is wrong, could it give out a syntax error if the Access database columns are not Data Type Short/Long Text?
The parameters are added properly (checked the debug).
Actually, I often find it too much work to create a complex insert routine. And even worse is I often don't care or want to supply all of the columns.
.net as a result has what is called a command builder for you.
And this quite much means you can write a lot of your code in a simular way to how VBA code in Access works.
So, say I want to add a new row - the table might have 50 columns, but I don't really care.
So, I can write the code this way:
Dim rstHotels As DataTable
rstHotels = MyRst("SELECT * FROM tblHotels WHERE ID = 0")
' now add 3 new hotels
For i = 1 To 3
Dim OneRow = rstHotels.NewRow
OneRow("HotelName") = "Hotel #" & i
OneRow("City") = "City #" & i
OneRow("FirstName") = "Test First name #" & i
OneRow("Active") = True
rstHotels.Rows.Add(OneRow)
Next
' ok, added rows to rstHotels - now write back to database
MyRstUpDate(rstHotels, "tblHotels")
' or update 5 rows and do compplex processing to exising data.
Dim rstFun As DataTable = MyRst("SELECT * from tblHotels where City = 'Banff'")
For Each MyRow As DataRow In rstFun.Rows
MyRow("Active") = True
' more complex cpde here
Next
' now send data changes back to database
MyRstUpdate(rstFun, "tblHotels")
So, note how we don't have to have some complex insert statement, and we don't hve to write some loop that gives one hoot about the number of columns. So the .net data operations have build in all this stuff for you - little or even next to no reason for you to try and re-invent the wheel here.
And the two handy dandy code routines I have? The are :
Public Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using conn As New OleDbConnection(My.Settings.AccessDB)
Using cmdSQL As New OleDbCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
rstData.TableName = strSQL
End Using
End Using
Return rstData
End Function
Public Sub MyRstUpdate(rstData As DataTable, strTableName As String)
Using conn As New OleDbConnection(My.Settings.AccessDB)
Using cmdSQL As New OleDbCommand("SELECT * from " & strTableName, conn)
Dim da As New OleDbDataAdapter(cmdSQL)
Dim daUP As New OleDbCommandBuilder(da)
conn.Open()
da.Update(rstData)
End Using
End Using
End Sub
Now, I am really rather free to just code out my general routines.
So, you need to say load up a grid, or even a combo box? You can now do this:
ListBox1.DataSource = MyRst("SELECT ID, Salutation from tblGender ORDER BY Salutation")
So, for a simple insert, or even edit of some rows? No need to create some monster huge insert statement with a boatload of parameters. Just create a data table, and then use a simple data row to either add new rows, or even update existing ones.
The beauty of above is not only do you eliminate a boatload of parameters, but you also get parameter safe, and even type conversions. So, you can for example do this:
OneRow("InvoiceDate") = Date.Today
Thus a strong typed value of "money" or integer, or datetime can be used in code - and no messey format convertions are required in most cases.
This so called "data base" first can be really handy, and often for some operations this is a lot less setup time and learning curve then say using EF, or even the previous dataset designer (EF = "Entity framework", which works really much like the older data set designer system - but introduction of these object model systems can be a big system to chew on when you just starting out).
But, no, don't write your own looping code to write out and create all the columns for a update command. (or insert command - note how that ONE routine can handle both updates or inserts. And you can even use row.Delete and then call tht update routine - it will also work!!.
If you think about this, that really amounts to a lot of work, and built in systems exist for this propose - saves you having to re-invent the wheel.
I'm dumb.
The order of the operations was off, this is what the function should have looked like:
Function SQL_InsertUpdate(mySQLConnection As OleDbConnection, mySQLCommand As String, mySQLTable As String, mySQLTableColumns() As String, myParameters() As String)
Dim myStringConstruct = mySQLCommand & " " & mySQLTable & " ("
'==============
For Each item In mySQLTableColumns
myStringConstruct = myStringConstruct & item & ", "
Next
myStringConstruct = Strings.Left(myStringConstruct, Len(myStringConstruct) - 2)
myStringConstruct = myStringConstruct & ") VALUES ("
For i As Integer = 0 To mySQLTableColumns.Length - 1
myStringConstruct = myStringConstruct & "#" & mySQLTableColumns(i) & ", "
Next
myStringConstruct = Strings.Left(myStringConstruct, Len(myStringConstruct) - 2)
myStringConstruct = myStringConstruct & ")"
Dim SQLCommand As OleDbCommand = New OleDbCommand(myStringConstruct, mySQLConnection)
For i As Integer = 0 To mySQLTableColumns.Length - 1
SQLCommand.Parameters.AddWithValue("#" & mySQLTableColumns(i), myParameters(i))
Next
SQLCommand.ExecuteNonQuery()
End Function
Basically, I was passing an incomplete command.

Storing information in the access database

Hi I'm trying to store the information of a new element in the datagrid, In the app is open the information is there, but when we close it and open it again, all the new information dissapear, can someone help?
Dim cmdSql As String
'If txtNumero.Text = "1" Then
cmdSql = "INSERT INTO Fatura (Cliente, Data, ValorTotal) " &
"VALUES ('" & txtCliente.Text & "', #" &
dataFatura.Value.ToString("dd/MM/yyyy") & "#, " &
Replace(txtValorTotal.Text.ToString, ",", ".") & ")"
GerirLigacao.ExecutarCmdSQL(cmdSql)
cmdSql = "SELECT TOP 1 Numero FROM Fatura ORDER BY Numero DESC"
Dim r As DataSet = GerirLigacao.obterDados(cmdSql)
txtNumero.Text = r.Tables(0).Rows(0).Item("Numero")
txtNrFatura.Text = txtNumero.Text
Dim msg = "Fatura guardada com sucesso"
Dim titulo = "Guardar"
Dim botoes = MessageBoxButtons.OK
Dim icone = MessageBoxIcon.Information
MessageBox.Show(msg, titulo, botoes, icone)
Gerirligacao
Public Shared Sub ExecutarCmdSQL(ByVal comando As String)
Try
Dim cmdSql As New OleDbCommand(comando, ligacao)
cmdSql.ExecuteNonQuery()
Catch ex As Exception
Dim msg = "Aconteceu um erro de execução." & vbNewLine
Dim botoes = MessageBoxButtons.OK
Dim icone = MessageBoxIcon.Error
MessageBox.Show(msg & ex.Message, "ERRO", botoes, icone)
End Try
End Sub
Look for the database file in the Solution Explorer, click on it and in the Properties grid set Copy To Output Directory to Copy If Newer
More info: https://social.technet.microsoft.com/wiki/contents/articles/53248.visual-studio-copying-files-to-debug-or-release-folder.aspx
Now might also be a good time to tell you that you could make some serious improvements to your database access code; this way you're doing it makes things very hard work and the code is highly insecure (take a read of http://bobby-table.com for more info). Microsoft used to have a great set of walkthroughs at http://msdn2.microsoft.com/en-us/library/fxsa23t6(vs.80).aspx - that documentation has now been archived (being at least 15 years old) and I cant download them on a cellphone to check it "creating a simple data application" is still prt of it. There are a good number of tutorials on YouTube about how to use tableadapters and datasets if that's the route you want to use, though the modern technology (and widest spread of knowledge) these days is probably available for Entity Framework. Google for "getting started with entity framework" and take a look; I'd highly recommend you go this way than your existing route of using weakly typed datasets and direct sql queries

5k+ SQL inserts takes a long time - how can I improve it?

Usually I only run this loop with less than 50 and it runs fine. Now I am trying to scale up and with 5k+ it takes serveral minuts.
Public Shared Sub Add(type As BufferType, objIDs As List(Of Integer), userToken As String)
Dim timeInUTCSeconds As Integer = Misc.UTCDateToSeconds(Date.Now)
For Each objID As Integer In objIDs
Dim insertStmt As String = "IF NOT EXISTS (SELECT ObjectID From " & TableName(type) & " where ObjectID = " & objID & " and UserToken = '" & userToken.ToString & "')" & _
" BEGIN INSERT INTO " & TableName(type) & "(ObjectID,UserToken,time) values(" & objID & ", '" & userToken.ToString & "', " & timeInUTCSeconds & ") END" & _
" ELSE BEGIN UPDATE " & TableName(type) & " set Time = " & timeInUTCSeconds & " where ObjectID = " & objID & " and UserToken = '" & userToken.ToString & "' END"
DAL.SQL.Insert(insertStmt)
Next
End Sub
You should always use SQLBULKCOPY for inserting a large amount of data. You can have a look at here which has been always considered as the best practice for inserting a large amount of the data into the table.
A demo code will make your fact clear, which has been taken from here
private static void PerformBulkCopy()
{
string connectionString =
#"Server=localhost;Database=Northwind;Trusted_Connection=true";
// get the source data
using (SqlConnection sourceConnection =
new SqlConnection(connectionString))
{
SqlCommand myCommand =
new SqlCommand("SELECT * FROM tablename", sourceConnection);
sourceConnection.Open();
SqlDataReader reader = myCommand.ExecuteReader();
// open the destination data
using (SqlConnection destinationConnection =
new SqlConnection(connectionString))
{
// open the connection
destinationConnection.Open();
using (SqlBulkCopy bulkCopy =
new SqlBulkCopy(destinationConnection.ConnectionString))
{
bulkCopy.BatchSize = 500;
bulkCopy.NotifyAfter = 1000;
bulkCopy.SqlRowsCopied +=
new SqlRowsCopiedEventHandler(bulkCopy_SqlRowsCopied);
bulkCopy.DestinationTableName = "Tablename";
bulkCopy.WriteToServer(reader);
}
}
reader.Close();
}
}
Also do not forget to read the documentation related to the Batchsize
Hope that helps.
Best option is to move whole work to SQL side. Pass your objIDs list as table parameter to stored procedure and utilize MERGE..UPDATE..INSERT statement.
If you require VB side code, there is number of optimization you can do.
SQL Parameters. Must do.
Check DAL.SQL class if it handles connection properly.
Construct single batch from commands and run it as whole batch.
(I'm assuming a reasonably recent version of SQL Server on probability given it's a .Net question.)
If at all possible, move this into a stored procedure that takes either a table-valued parameter or delimited string of IDs.
Parameterise your queries. When the DBMS is executing a string of code with no parameters, it can't work out which bits are constant and which are parameters - so it works out a new execution plan each time. With parameters for the data, it'd reuse execution plans and run faster.
With really big repetitive jobs, connection latency can become a surprisingly big issue. If you really have to execute something like this as ad-hoc SQL from the calling app (which I wouldn't for this, but it's your project), try batching the statements and executing them en masse rather than issuing 5000 individual connections. Should be significantly faster.

datatypes dont match, correct query and table

Got a new one for you, tried everything i could think of but without succes.
I want to be able to edit some textboxes and then update their records in the database. I use this code:
Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click
connection.Open()
cmdupdate.CommandText = "UPDATE tbl_stal SET Locatie = '" & cbLocatienummer.Text & "', Coordinaten = '" & txtCoordinaten.Text & "' WHERE ID = '" & cbID.Text & "'"
cmdupdate.CommandType = CommandType.Text
cmdupdate.Connection = connection
cmdupdate.ExecuteNonQuery()
MsgBox("De gegevens zijn aangepast." & vbNewLine & "The data has been modified." & vbNewLine & "Die Daten sind angepasst.", MsgBoxStyle.OkOnly, "Voersoorten")
connection.Close()
cmdupdate.Dispose()
I am certain that the names of the database table and it's fields are correct, tried using both numerical and textbased settings on the table fields(as normally they should be numerical, but they might be text too. )
However, when i load some data from the datagridvieuw into the textboxes, change the coordinates(for example) and hit the updatebutton, it will give me the error that the datatypes don't match.
Apart from the above, what else can it be?
When you write data to a database table using any kind of sql text you should NEVER use string concatenation to build the SQL. This because you could have problems in the string supplied (what if one of these strings contains an embedded single quote?) and because taking the user input and attaching it to your command is a really dangerous practice that leads to Sql Injection
(Well MS-Access doesn't support multiple commands so you are a bit safer here)
So you should rewrite your query in this way
Dim cmdText = "UPDATE tbl_stal SET Locatie = ?, Coordinaten = ? WHERE ID = ?"
Using connection = new OleDbConnection(.....)
Using cmdUpdate = new OleDbCommand(cmdText, connection)
connection.Open()
cmdUpdate.Parameters.AddWithValue("#p1", cbLocatienummer.Text)
cmdUpdate.Parameters.AddWithValue("#p2", txtCoordinaten.Text)
cmdUpdate.Parameters.AddWithValue("#p3", Convert.ToInt32(cbID.Text))
cmdUpdate.ExecuteNonQuery()
End Using
End Using
Notice that you should provide a parameter with the exact datatype that matches the datatype of your field, strings for text fields, numbers for numeric fields.

VB.NET Linq to SQL - Query from table

I am starting with Linq to SQL in VB.NET, and trying to figure out how to make a simple query to a database.
I want to do it all programaticly.
I have made a connection to the database with a connectionstring, and this works fine - I can get a message if the database exists or not.
But when I want to query a table, I am missing the part where I connest to the table. I have googled a lot to find an answer for thi, but
no luck. Can anyone point me in the right direction?
Code:
Dim strContactString, strDBServer, strDBName, strSQLUser, strSQLPW As String
strDBServer = "MyServer"
strDBName = "Northwind"
strSQLUser = "sa"
strSQLPW = "MyPW"
strContactString = ""
strContactString = strContactString & "data source=" & strDBServer & ";"
strContactString = strContactString & "initial catalog=" & strDBName & ";"
strContactString = strContactString & "user id=" & strSQLUser & ";"
strContactString = strContactString & "password=" & strSQLPW & ";"
Dim MyContext As New DataContext(strContactString)
'This works:
If MyContext.DatabaseExists Then
MsgBox("DB Exists")
Else
MsgBox("DB Does Not Exist")
End If
'This is the query I want to run (copied from samples I found)
Dim TEST = From c In MyContext.Customers _
Select c.ContactName
Error message:
'Customers' is not a member of 'System.Data.Linq.DataContext'.
First off you're not supposed to use DataContext directly.
You add a new dbml file to your project and map that to the database using the editor (this means connecting visual studio to your database, then dragging the tables you want from the server explorer to the dbml editor).
That will generate for you a class colled something like NortwindDataContext (you can control this from the properties pane in the editor).
You can then use that to write your queries:
Dim context As New DataContext(strContactString)
Dim TEST = From c In context.Customers _
Select c.ContactName
http://msdn.microsoft.com/en-us/library/bb399375.aspx
"Best practice is to declare a strongly typed DataContext instead of relying on the basic DataContext class and the GetTable method. A strongly typed DataContext declares all Table collections as members of the context, as in the following example."
As long as the db is connected correctly, this may be your problem.