Updating date in SQL/VB/Asp.Net - mysql

I'm pretty much a novice at all this. I know bits. Just trying to store a date in an SQL database. I've set it to 06/06/2015 temporarily in code below to see if I can get it to update but it updates it as 01/01/0001. When I suss it, The value I actually want to store is todays date plus 6 months. EG: if its 31/07/2015 today, I want it to store 31/01/2016. Can anyone help ? Much appreciated...
ASPX.VB
Protected Sub imgBtnDatechange_Click(sender As Object, e As ImageClickEventArgs) Handles imgBtn.Click
Dim acc As New accounts(Membership.GetUser().ProviderUserKey)
Dim adjustedDate as Date = "06/06/2015"
acc.UpdateVipEndDate(acc.accountID, acc.adjustedDate)
End Sub
ACCOUNTS.VB
Public Property adjustedDate As Date
Public Sub UpdateVipEndDate(ByVal accountID As Guid, ByVal adjustedDate As Date)
Dim DBConnect As New DBConn
Using db As DbConnection = DBConnect.Conn("DBConnectionString")
Dim cmd As SqlCommand = DBConnect.Command(db, "UpdateVipEndDate")
cmd.Parameters.Add(New SqlParameter("accountID", SqlDbType.UniqueIdentifier, ParameterDirection.Input)).Value = accountID
cmd.Parameters.Add(New SqlParameter("newadjustedDate", SqlDbType.Date, ParameterDirection.Input)).Value = adjustedDate
db.Open()
cmd.ExecuteNonQuery()
cmd.Dispose()
cmd = Nothing
db.Dispose()
db.Close()
End Using
End Sub
STORED PROCEDURE
CREATE PROCEDURE [UpdateVipEndDate]
#accountID uniqueidentifier,
#newadjustedDate date
AS
BEGIN
UPDATE tblAccounts SET [vipEndDate] = #newadjustedDate WHERE [accountID] = #accountID
END

You set a date here:
Dim adjustedDate as Date = "06/06/2015"
But you never use that variable anywhere. Instead, you're using a parameter on the acc object:
acc.UpdateVipEndDate(acc.accountID, acc.adjustedDate)
So, presumably, the acc.adjustedDate value is otherwise empty or some default MinDate value.
It seems like you're confusing a few things here...
If something is a Date, use it as a Date. Not as a String.
If the UpdateVipEndDate method is on the acc object, why do you need to pass it references to its own parameters? It should be able to access those values internally in the method.
I'm probably getting off point here, though. The simplest thing, it seems, would be to not use a local variable and use the object member that you use elsewhere:
acc.adjustedDate = "06/06/2015"

Related

Populating ListBox More Quickly

Is there a way to make populating ListBox fast, because the UI is freezing on form load upon populating the ListBox?
This is my form load code:
Dim abc As String = itemCount()
Dim output = Account_Get(a)
For Each s In output
ListBox1.Items.Add(s)
count1 += 1
If count1 = abc Then
ListBox1.Visible = True
End If
Next
This is the query in module:
Public Function Account_Get(ByVal chk As String) As List(Of String)
Dim result = New List(Of String)()
Try
cn.Open()
sql = "select column_name as str from table where status = 'New' order by rand()"
cmd = New MySqlCommand(sql, cn)
dr = cmd.ExecuteReader
While dr.Read
result.Add(dr("str").ToString())
End While
Return result
Catch ex As Exception
MsgErr(ex.Message, "Error Encounter")
Return Nothing
Finally
cn.Close()
End Try
End Function
this is working fine. but the fact that it loads too many datas. the ui is freezing on load. hoping someone could help me with this. thanks!
Since you are incrementing count1 I assume it is some sort of number. However, you are then comparing it to a string in the If statement. Please use Option Strict.
Changed the Function to return an Array of String. Took the random sort form the sql statement and moved it to a little linq at the end or the function.
You could add a Stopwatch to the data retrieval and the display sections to see where your bottleneck is. BeginUpdate and EndUpdate on the listbox prevents repainting on every addition.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim output = Account_Get()
ListBox2.BeginUpdate()
ListBox2.Items.AddRange(output)
ListBox2.EndUpdate()
End Sub
Private Rand As New Random
Public Function Account_Get() As String()
Dim dt As New DataTable
Dim result As String()
Using cn As New MySqlConnection("Your connection string")
Dim Sql = "select column_name as str from table where status = 'New'" 'order by rand()"
Using cmd = New MySqlCommand(Sql, cn)
Try
cn.Open()
dt.Load(cmd.ExecuteReader)
Catch ex As Exception
MessageBox.Show(ex.Message, "Error Encounter")
Return Nothing
End Try
End Using
End Using
result = (From dRow In dt.AsEnumerable()
Let field = dRow("str").ToString
Order By Rand.Next
Select field).ToArray
Return result
End Function
The query you are using contains a random order. Ordering records randomly can be a huge performance issue within MySQL as it has to go through all records in the table and then sort them randomly. The more records in the table, the bigger the performance penalty. There is also no limitation on the number of records in your query. So if there are thousands of items in your table the listbox will also be thousands of items in size, which could also take a long time.
If you really require the random ordering you could do something about it in your code. I'm now assuming here that you are: 1) using identifiers in your table, 2) you actually wish to limit the number of items in your listbox and not display all of them.
Get a grasp of the total number of records in the table by a query
Pick a random number from the range of items in your table
Fetch the nearest record
Hope this helps you to get going to find a solution

DIsplay real time SQL data on web form

I am working on a small project but currently stuck in the process and your help would be much appreciated.
I am trying to display data from one of my SQL tables onto web form (asp), which will effectively be updating as long as data is being entered into the table.
I have managed to get it to work by using the META Tag which refreshes the page every 2 seconds, but I know this is not an ideal way of doing it. It was advised to me to update the web form only from server to client when there is a new inserted value, however I do not know how to approach this.
Please see below to my current code.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Label1.Text = "Cache Refresh:" & _
Date.Now.ToLongTimeString
SqlDependency.Start(GetConnectionSTring())
Using connection As New SqlConnection(GetConnectionSTring())
Using Command As New SqlCommand(GetSQL(), connection)
Dim Dependency As New SqlCacheDependency(Command)
Dim NumberOfMinutes As Integer = 3
Dim Expires As Date = _
DateTime.Now.AddMinutes(NumberOfMinutes)
Response.Cache.SetExpires(Expires)
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(True)
Response.AddCacheDependency(Dependency)
connection.Open()
GridView1.DataSource = Command.ExecuteReader()
GridView1.DataBind()
End Using
End Using
End Sub
Private Function GetConnectionSTring() As String
Return "Data Source=xxxxxxxxx; Initial Catalog=Test; User ID=xxx; Password= xxx;"
End Function
Private Function GetSQL() As String
Return "SELECT ProductCode, ProductName, Cost FROM dbo.OrderTempTable"
End Function
Thank you for your input.
I think you have to check the DB every certain time.
THIS is for PHP but the idea is the same.
HERE another example.

Populate a textbox with mysql data after a combobox selection

So I have 2 mysql tables, one called "Service_Details" and one called "Payment_details"
I have a combobox in my form which displays the "service_id" field from the service table.
I'm trying to code a textbox, so when I select the service id from the combobox it writes the "service" which is another field in my service details table. The service id is linked to a service.
I am getting errors 'identifier expected' at [0] and 'Value of type 'system.data.datatablecollection' cannot be converted to 'string' at dss.tables
I can't seem to get it working after browsing the internet for an hour
Here is my code:
Private Sub cbxserviceid_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbxserviceid.SelectedIndexChanged
Dim dss As New DataSet
Dim daa As New MySqlDataAdapter("SELECT * from service_details WHERE ServiceID='" + cbxserviceid.Text + "'", objconnection)
Dim cmddd = New MySqlCommandBuilder(daa)
daa.Fill(dss)
txtService1.Text = dss.Tables[0].Rows[0]["Service"].ToString();
End Sub
The indexes in VB.NET are expressed using the round braces, the square brackets are used in C#
txtService1.Text = dss.Tables(0).Rows(0)("Service").ToString()
Also avoid to use string concatenation for sql command texts, use always a parameterized query
Private Sub cbxserviceid_SelectedIndexChanged(......)
Dim dss As New DataSet
if cbxserviceid.SelectedIndex <> -1 Then
Dim daa As New MySqlDataAdapter("SELECT * from service_details WHERE ServiceID=#id", _
objconnection)
daa.SelectCommand.Parameters.AddWithValue("#id", Convert.ToInt32(cbxserviceid.Text))
daa.Fill(dss)
txtService1.Text = dss.Tables(0).Rows(0)("Service").ToString()
End If
End Sub
I have also removed the creation of the MySqlCommandBuilder, being the adapter a local variable it has no sense or effect (if this is all your code in this event of course).
Looking at the comments below and the chat with the poster there is also another error to fix.
When assign a DataSource, DisplayMember and ValueMember property of a combobox it is mandatory to follow a precise order to avoid unwanted side effects
cbxserviceid.DisplayMember = "ServiceID"
cbxserviceid.ValueMember = "ServiceID"
cbxserviceid.DataSource = datatable

VB.NET MySqlCommand Stored Procedure Parameter Order?

I create a dictionary in a function which I pass to the function executing the sproc.
Dim PParamDict As New Dictionary(Of String, String)
PParamDict.Add("sname", name)
PParamDict.Add("sdescription", description)
PParamDict.Add("sLoggedInID", LoggedInID)
PParamDict.Add("sCompanyID", CompanyID)
The dictionary gets passed to the function PParamDict -> ParameterDict
Dim dbComm As New MySqlCommand(ProcedureName, PConnection)
Dim pair As KeyValuePair(Of String, String)
For Each pair In ParameterDict
dbComm.Parameters.AddWithValue(pair.Key, pair.Value)
Next
Parameters are added from the dictionary.
This is a straightforward sproc, nothing special about it, a simple insert.
CREATE PROCEDURE `NewCollection`(
IN `sLoggedInID` INT(5),
IN `sCompanyID` INT(5),
IN `sname` VARCHAR(20),
IN `sdescription` VARCHAR(500))
BEGIN
INSERT INTO `collection`
(`userid`, `companyid`, `name`, `description`, `generated`)
VALUES
(sLoggedInID, sCompanyID, sname, sdescription, CURRENT_TIMESTAMP);
END
This works as long as the PParamDict.Add statements are in that order. If they're in a different order they get passed as they come in. This is the most ridiculous thing I've ever seen, I'm passing the damn keys to the MySqlCommand which are defined letter for letter in the sproc. I must be missing something, please help!
I have a similar problem, however my list of parameter values has come via reflection so I don't build a list manually and have no control of the order.
In Pete's answer, the binding of the parameters will always be in the correct order because it is not a stored procedure, but a text command where the parameter names are used as place holders so it won't matter which order they are added.
To get around the ordering problem I simply explicity call the procedure as text (like Pete's INSERT) rather than use command.CommandType = System.Data.CommandType.StoredProcedure like this:
command.CommandText = "call procname (#param1, #param2, #param3 ... );"
Then I can add my parameters in any order i want
command.Parameters.AddWithValue("#param3", 123)
command.Parameters.AddWithValue("#param2", 456)
command.Parameters.AddWithValue("#param1", 789)
Hope this helps.
EDIT: This method won't work if you have output parameters
Perhaps this will help. A StringDictionary "implements a hash table with the key and the value strongly typed to be strings rather than objects".
A HashTable "represents a collection of key/value pairs that are organized based on the hash code of the key".
As you add pairs to your StringDictionary, it gets reorganized by the hash code of the key string.
If you build a SqlParameterCollection instead of a StringDictionary, your parameters are named and a for each iterator should match the parameters in your sproc nicely.
UPDATE
Adding code example.
Private Function GetParameters(ByVal name As String, ByVal description As String, ByVal LoggedInID As Integer, ByVal CompanyID As Integer) As SqlParameterCollection
Dim cmd As SqlCommand = New SqlCommand()
Dim pc As SqlParameterCollection = cmd.Parameters 'SqlParameterCollection constructor is marked as "Friend" so it has to be instantiated this way.'
pc.AddWithValue("sname", name)
pc.AddWithValue("sdescription", description)
pc.AddWithValue("sLoggedInID", LoggedInID)
pc.AddWithValue("sCompanyID", CompanyID)
Return pc
End Function
Private Sub ExecuteStoredProcedure(ByVal pc As SqlParameterCollection)
Dim sp As String = String.Empty
Dim conn As SqlConnection = Nothing
Dim cmd As SqlCommand = Nothing
Dim da As SqlDataAdapter = Nothing
Dim ds As DataSet = Nothing
Dim p As SqlParameter = Nothing
Try
sp = "INSERT INTO `collection` (`user_id`, `company_id`, `name`, `description`, `generated`) VALUES (`sLoggedInID`, `sCompanyID`, `sname`, `sdescription`, CURRENT_TIMESTAMP)"
conn = New SqlConnection("your connection string here")
cmd = New SqlCommand(sp, conn)
For Each p In pc
cmd.Parameters.Add(p)
Next
da = New SqlDataAdapter(cmd)
ds = New DataSet
da.Fill(ds)
Catch ex As SqlException
'handle exception'
Catch ex As Exception
'handle exception'
Finally
If conn IsNot Nothing Then
conn.Dispose()
End If
If cmd IsNot Nothing Then
cmd.Dispose()
End If
If da IsNot Nothing Then
da.Dispose()
End If
End Try
End Sub

grab linq to sql record by primarykey without knowing its type

how can i grab a record (and eventually delete it) using linq2sql without knowing the type at compile time?
so far i've got
Sub Delete(ByVal RecordType As String, ByVal ID As Integer)
Dim dummy = Activator.CreateInstance(MyAssembly, RecordType).Unwrap
Dim tbl = GetTable(dummy.GetType)
tbl.DeleteOnSubmit(dummy)
End Sub
but of course the dummy is not an actual record, its just a dummy
i don't want to use direct sql (or executecommand) as there's business logic going on at deletion in the datacontext partial class
can this be done somehow?
thank you very much!
EDIT
in response to striplinwarior, i edited my code to:
Sub Delete(ByVal RecordType As ObjectType, ByVal ID As Integer)
Dim dummy = Activator.CreateInstance(ObjectType.Account.GetType.Assembly.FullName, RecordType.ToString).Unwrap
SetObjProperty(dummy, PrimaryKeyField(RecordType), ID)
Dim tbl = GetTable(dummy.GetType)
tbl.Attach(dummy)
tbl.DeleteOnSubmit(dummy)
SubmitChanges()
End Sub
this does fire off the deletion code correclty, but also seems to try to add the record first to the db, as i get a sqlexception that some "not null" fields are empty, which i guess is true about the dummy record, as the only thing this has is the primarykey, else is all empty. so i tried the other code u posted (something i anyways always wanted to have) and that works excellent!
hers my current code:
Function LoadRecord(ByVal RecordType As String, ByVal RecordID As Integer) As Object
Dim dummy = Activator.CreateInstance(AssemblyName, RecordType).Unwrap
Dim rowType = dummy.GetType
Dim eParam = Expression.Parameter(rowType, "e")
Dim idm = rowType.GetProperty(PrimaryKeyField(RecordType))
Dim lambda = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(eParam, idm), Expression.Constant(RecordID)), eParam)
Dim firstMethod = GetType(Queryable).GetMethods().[Single](Function(m) m.Name = "Single" AndAlso m.GetParameters().Count() = 2).MakeGenericMethod(rowType)
Dim tbl = GetTable(rowType)
Dim obj = firstMethod.Invoke(Nothing, New Object() {tbl, lambda})
Return obj
End Function
Sub Delete(ByVal RecordType As String, ByVal RecordID As Integer)
Dim obj = LoadRecord(RecordType, RecordID)
Dim tbl = GetTable(obj.GetType)
tbl.DeleteOnSubmit(obj)
SubmitChanges()
End Sub
Thank You
The only way I can think of is to use the model information from your database mapping to figure out which member represents the primary key:
Dim primaryKey = (From t In db.Mapping.GetTables() _
Where t.RowType.Type = tableType _
Let keyMember = (From dm In t.RowType.DataMembers where dm.IsPrimaryKey).FirstOrDefault() _
Select keyMember.Member.Name).First()
(I'm using LinqPad here: I assume typical LINQ to SQL models have this mapping information available.)
Then use reflection to set the value of that key member on the dummy item you've created. After that, you need to attach the dummy to the table before trying to delete it, passing false as a second parameter to tell LINQ to SQL that you don't actually want to update the object using its current values, but that it should track changes from here on.
tbl.Attach(dummy, false)
tbl.DeleteOnSubmit(dummy)
db.SubmitChanges()
Does that make sense?
Edit
When you're only deleting an object, you don't necessarily have to get the record from the database. If you set the ID value of the object and then attach it to the context (as shown above), LINQ to SQL will treat it as if it were retrieved from the database. At that point, calling DeleteOnSubmit should tell the context to construct a DELETE statement in SQL based on that object's primary key value.
However, if you need to retrieve the object for some purpose other than deletion, you'll need to construct an expression to represent the query for that object. So, for example, if you were writing the query manually, you would say something like:
Dim obj = tbl.First(Function(e) e.Id = ID)
So to dynamically build the lambda expression inside the parentheses, you might do something like this:
Dim eParam = Expression.Parameter(rowType, "e")
Dim lambda = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(eParam, idMember), Expression.Constant(ID)), eParam)
Then you would need to use reflection to invoke the generic First method:
Dim firstMethod = GetType(Queryable).GetMethods().[Single](Function(m) m.Name = "Single" AndAlso m.GetParameters().Count() = 2).MakeGenericMethod(rowType)
Dim obj = firstMethod.Invoke(Nothing, New Object() {tbl, lambda})