.Net: code for BtnLock_Click - asp.net

I have been trying to apply a solution to some functionality that a user requires on their system.
A user requires me to implement a locking system on their system. They have multiple users which may require to access the site, but the user would like the ability for them to independently lock a records in the web site site, for them to add notes to and to then unlock this so other users are able to do the same.
I have a button on my web page simply named btnLock and i have added an additional column in my database called LockedBy and have the following stored procedure...
ALTER PROCEDURE LockWeeklyTest
(
#AgendaID BIGINT,
#LockingUser VARCHAR(20)
)
AS
BEGIN
SET NOCOUNT ON
UPDATE
WeeklyAgenda
SET
LockedBy = #LockingUser
WHERE
AgendaID = #AgendaID
AND
LockedBy IS NULL
END
I have a class named Weekly Class and have the following code...
Public Shared Sub LockWeeklyAgenda(ByVal WeeklyClass As WeeklyClass)
Using dbConnection As New SqlConnection(ConfigurationManager.AppSettings("dbConnection"))
dbConnection.Open()
Dim dbTrans As SqlTransaction
dbTrans = dbConnection.BeginTransaction()
Using dbCommand As SqlCommand = dbConnection.CreateCommand
With dbCommand
.Transaction = dbTrans
.CommandType = CommandType.StoredProcedure
.CommandText = "LockWeeklyTest"
'Add Parameters for Update
.Parameters.AddWithValue("#AgendaID", WeeklyClass.AgendaID)
.Parameters.AddWithValue("#LockingUser", WeeklyClass.LockedBy)
dbCommand.ExecuteNonQuery()
End With
End Using 'dbCommand
dbTrans.Commit()
End Using
End Sub
I was thinking that the below code for the butlock would populate my Loggedby field with the username but this isnt the case.
Protected Sub btnLock_Click(sender As Object, e As System.EventArgs) Handles btnLock.Click
Dim lock As New WeeklyClass
If lock.LockedBy = "Null" Then
lock.LockedBy = System.Environment.UserName
'lock.AgendaID = AgendaID
End If
' save to the database using the Class DAL
WeeklyClassDAL.LockWeeklyAgenda(lock)
End Sub
I know that the Stored Procedure works as i have tested with the following statement as an example...
EXEC LockWeeklyTest 11, 'Betty'
Im sure that its something to do with the btnlock_click, but im not 100% sure what this is.
Any help is much appriechiated.

Your problem is this line:
If lock.LockedBy = "Null" Then
"Null" is actually a string containing the word Null. What you're after is:
If String.IsNullOrEmpty(lock.LockedBy) Then
That way, if it is actually null or empty, your LockedBy will be set. Currently, it's only setting the LockedBy if LockedBy already equals the string value "Null", which it won't directly after being declared. Is this logic really necessary considering LockedBy will always be null directly after you've declared the WeeklyClass?

Something doesn't look quite right with the AgendaID:
During the button click event the value has been commented out but is still passed through to the stored procedure inside the data layer's 'LockWeeklyAgenda' method.
It's also not defined as a nullable parameter inside the stored procedure itself, so the value that's being sent would depend on the WeeklyClass class' constructor..
can you please also show how the WeeklyClass code looks like?

Related

Error when using the WHERE clause in Linq-to-SQL

I have a datacontext that I'm trying to query, the results of which I want to bind to a gridview on a button click. Getting connected to the datacontext works great. I get the 1000s of records I expect. When I try to add the WHERE clause, I run into problems. Here's the button event I'm trying to make it happen at:
Protected Sub btnSearch_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim dsource = New MY_DataContext().SV_XXXs '--- This works, the data is all there
gridRec.DataSource = dsource.ToList().Where(Function(dtable) dtable.PN = Session("PN")) '--- this fails
'--- Also tried this, it also did not work ----------------------------------------------------------
'--- gridRec.DataSource = dsource.Where(Function(dtable) dtable.PN = Session("PN")) '--- this fails
'----------------------------------------------------------------------------------------------------
gridRec.DataBind()
End Sub
The session variable is valid and the dsource is populating correctly, but I get the following error when it tries to execute the Where clause:
Evaluation of method
System.Linq.SystemCore_EnumerableDebugView`1[SV_REC].get_Items() calls
into native method System.WeakReference.get_Target(). Evaluation of
native methods in this context is not supported.
Also tried:
Dim results =
(
From T In dsource
Where T.PN = Session("SAFRReceiverPN")
Select T
).ToList
And get this error
Method 'System.Object CompareObjectEqual(System.Object, System.Object,
Boolean)' has no supported translation to SQL.
And tried:
Dim results = From t In dsource Where (t.PN = Session("SAFRReceiverPN")) Select t
nothing seems to work for me when trying a WHERE clause
C# or VB.NET are both cool if you have any suggestions.
Really, any help is appreciated, thanks.
LINQ to SQL doesn't know what to do when you try to access the session inside the query. Instead of doing that, fetch the value from the session before the query and store the result in a local variable, then use that local variable in your query. For example, in C#:
var receiver = (string) Session["SAFRReceiverPN"];
var results = dsource.Where(t => t.PN == receiver);
(I don't bother with query expressions when you're just trying to perform a simple filter.)

Identity of recently added record and insert from gridview?

I am developing an ASP.Net VB Web Application
The application contains a GridView which displays the records of a user table from my created datable. The database is an Sql server database.
The code below inserts data into one table and through the built in function ##Identity to insert the most recently added record id (tt_id) from the trainingTbl table and inserting that record id into the userAssessmentTbl. Adding the identity to the second userAssessmentTbl table works fine.
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim lblUsr2 As Control = FindControlRecursive(MultiTabs, "txtUsr")
Dim strQuery As String
Dim cmd As SqlCommand
strQuery = "Insert into trainingTbl(s_id, t_date, EditorId, wa_id, st_id) values(#s_id , #t_date, #EditorId, #wa_id, #st_id ) Insert into userAssessmentTbl(tt_id, UserId) values(##Identity, #UserId)"
cmd = New SqlCommand(strQuery)
cmd.Parameters.AddWithValue("#s_id", DDLCourse.Text)
cmd.Parameters.AddWithValue("#t_date", Convert.ToDateTime(txtDate.Text))
cmd.Parameters.AddWithValue("#EditorId", User.Identity.Name.ToString())
cmd.Parameters.AddWithValue("#st_id", myLblStation.Value().ToString)
cmd.Parameters.AddWithValue("#wa_id", myLblWatch.Value().ToString)
cmd.Parameters.AddWithValue("#UserId", lblUsr2.UniqueID.ToString)
InsertUpdateData(cmd)
End Sub
The issue I’m having seems to be centered on how I insert a uniqueidenifier from a GridView into a userAssessmentTbl database!
And how, I guess using a loop I can insert the UserId records from that Gridview (GridView1) into the userAssessmentTbl table along with the looped id from the ##Identity.
This part of the insert parameter seems to be incorrect:
cmd.Parameters.AddWithValue("#UserId", lblUsr2.UniqueID().ToString)
And the error I’m met with is: 'Conversion failed when converting from a character string to uniqueidentifier.'
I’ve also tried it like this:
cmd.Parameters.AddWithValue("#UserId", SqlDbType.UniqueIdentifier).Value().ToString()
And im met with the error: 'Operand type clash: int is incompatible with uniqueidentifier'
The qusetion has slightly changed to how do I Insert a String into SQL DB Where DataType Is Uniqueidentifier?
Any help will be really appreciated.
Well first of all:
##IDENTITY returns the most recently created identity for your current
connection, not necessarily the identity for the recently added row in
a table. Always use SCOPE_IDENTITY() to return the identity of the
recently added row.
Secondly, to asnwer your question:
The SQL type Uniqueidentifier and the CLR type Guid match up.
So instead of passing "#UserId" in as a parameter you need to create a Guid out of the string value.
Dim userID As Guid = New Guid(lblUsr2.UniqueID.ToString)

Inserting null values into date fields?

I have a FormView where I pull data from one table (MS Access), and then insert it (plus more data) into another table. I'm having issues with the dates.
The first table has two date fields: date_submitted and date_updated. In some records, date_updated is blank. This causes me to get a data mismatch error when attempting to insert into the second table.
It might be because I'm databinding the date_updated field from the first table into a HiddenField on the FormView. It then takes the value from the HiddenField and attempts to insert it into the second table:
Dim hfDateRequestUpdated As HiddenField = FormView1.FindControl("hfDateRequestUpdated")
myDateRequestUpdated = hfDateRequestUpdated.Value
'... It then attempts to insert myDateRequestUpdated into the database.
It works when there is a value there, but apparently you can't insert nothing into a date/time field in Access. I suppose I could make a second insert statement that does not insert into date_updated (to use when there is no value indate_updated), but is that the only way to do it? Seems like there should be an easier/less redundant way.
EDIT:
Okay. So I've tried inserting SqlDateTime.Null, Nothing, and DBNull.Value. SqlDateTime.Null results in the value 1/1/1900 being inserted into the database. "Nothing" causes it to insert 1/1/2001. And if I try to use DBNull.Value, it tells me that it cannot be converted to a string, so maybe I didn't do something quite right there. At any rate, I was hoping that if there was nothing to insert that the field in Access would remain blank, but it seems that it has to fill it with something...
EDIT:
I got DBNull.Value to work, and it does insert a completely blank value. So this is my final working code:
Dim hfDateRequestUpdated As HiddenField = FormView1.FindControl("hfDateRequestUpdated")
Dim myDateRequestUpdated = Nothing
If hfDateRequestUpdated.Value = Nothing Then
myDateRequestUpdated = DBNull.Value
Else
myDateRequestUpdated = DateTime.Parse(hfDateRequestUpdated.Value)
End If
Thanks everyone!
Sara, have you tried casting the date/time before you update it? The data mismatch error likely comes from the fact that the hfDateRequestUpdated.Value you're trying to insert into the database doesn't match the column type.
Try stepping through your code and seeing what the type of that value is. If you find that it's a string (which it seems it might be, since it's coming from a field on a form), then you will need a check first to see if that field is the empty string (VBNullString). If so, you will want to change the value you're inserting into the database to DBNull, which you can get in VB.Net using DBNull.Value.
We can't see your code, so we don't know exactly how you get the value into the database, but it would look something like this
If theDateValueBeingInserted is Nothing Then
theDateValueBeingInserted = DBNull.Value
EndIf
Keep in mind that the above test only works if the value you get from the HiddenField is a string, which I believe it is according to the documentation. That's probably where all this trouble you're having is coming from. You're implicitly converting your date/time values to a string (which is easy), but implicitly converting them back isn't so easy, especially if the initial value was a DBNull
aside
I think what Marshall was trying to suggest was the equivalent of the above code, but in a shortcut expression called the 'ternary operator', which looks like this in VB.Net:
newValue = IF(oldValue is Nothing ? DBNull.Value : oldValue)
I wouldn't recommend it though, since it's confusing to new programmers, and the syntax changed in 2008 from IFF(condition ? trueResult : falseResult)
Your code
Dim myDateRequestUpdated As DateTime
myDateRequestUpdated = DateTime.Parse(hfDateRequestUpdated.Value) : DBNull.Value()
has a couple of problems:
When you declare myDateRequestUpdated to be DateTime, you can't put a DbNull.Value in it.
I'm not sure you need the () for DbNull.Value: it's a property, not a method (I don't know enough VB to say for sure)
VB doesn't know that : operator
What you probably want is a Nullable(Of DateTime) to store a DateTime value that can also be missing.
Then use something like this to store the value:
myDateRequestUpdated = If(String.IsNullOrWhiteSpace(hfDateRequestUpdated.Value),
Nothing, DateTime.Parse(hfDateRequestUpdated.Value))
If hfDateRequestUpdated.Value is empty, then use Nothing as the result; else parse the value as date (which might fail if it is not a valid date!).
Try this:
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim str As String
If TextBox1.Text.Length <> 0 Then
str = "'" & TextBox1.Text & "'"
Else
str = "NULL"
End If
sql = "insert into test(test1) values(" & str & ")"
dsave_sql(sql)
End Sub
Function save_sql(ByVal strsql As String, Optional ByVal msg As String = "Record Saved Sucessfully") As String
Dim sqlcon As New SqlConnection(strConn)
Dim comm As New SqlCommand(strsql, sqlcon)
Dim i As Integer
Try
sqlcon.Open()
i = CType(comm.ExecuteScalar(), Integer)
save_sql = msg
Catch ex As Exception
save_sql = ex.Message
End Try
sqlcon.Close()
Return i
End Function

Must I use parameters with an ObjectDataSource update?

I have a business object that I've been using, which has a bunch of properties and a Save method, which inserts/updates to the database. The save method is NOT status, so the object needs to be instantiated, and the properties for the DB update/insert get pulled from the object.
Now I'm trying to bind the object to a FormView with the ObjectDataSource. I have it working so it instantiates based on the QueryString parameter, no problem, and populates the textboxes just fine. The UpdateMethod I have set to the Save function. Now it gets stuck.
It seems the ObjectDataSource needs a method with all the fields/properties/textboxes as parameters. I would have thought it would update the object's properties and then call the parameterless Save function. Is this wishful thinking?
Do I now need to change my Save function to include parameters, and change all the instances where it's getting used to this new method, just for this reason?
Thanks
Sean
Unfortunatly it does require params.
I overloaded my insert/update methods to include a few params. Attach the ObjectDataSource to the method with params.
The overloaded Update method calls the original Update method saving all the data. Seems kind of hackish to me, but it works.
Public Sub Update()
Dim isUpdated As Boolean = False
sql = "UPDATE AudioFiles SET Title = #Title, [desc] = #desc, Active = #Active WHERE fileID = #fileID"
conn = New SqlConnection(connString)
conn.Open()
...
End Sub
Public Sub Update(ByVal upFileID As Integer, ByVal upTitle As String, ByVal upDesc As String, ByVal upActive As Boolean)
Dim isUpdated As Boolean = False
Dim audioFile As New AudioFiles(fileID)
If Len(upTitle) > 0 Then
_title = title
End If
...
audioFile.Update()
End Sub

ADO error "Current Recordset does not support updating. This may be a limitation of the provider, or of the selected locktype."

I am doing some calculation with the data set I take from my database. Null values give errors so I tried replacing null values with zeros(0). Here is the error I get,
ADODB.Recordset error '800a0cb3'
Current Recordset does not support
updating. This may be a limitation of
the provider, or of the selected
locktype.
Never seen it before. Here is my code.
If IsNull(objRevenueToday("REVENUE")) Then
objRevenueToday("REVENUE") = 0
End If
Your recordset appears to be read-only. There could be a number of reasons for this; you're reading a view that contains a Group By clause, you don't have permissions, etc.
Using the syntax Set Recordset = Command.Execute always opens a read only cursor. What you need to do is open the cursor using the Recordset object. The Source parameter of the Open method is your Command object. This allows you to set the desired location and locktype.
Dim cmdProc as ADODB.Command
Dim rsData as ADODB.Recordset
Set cmdProc = New ADODB.Command
With cmdProc
Set .ActiveConnection = SomeConnection
.CommandType = adCmdStoredProc
.CommandText = "selCustomer"
' ... Create parameters
End With
Set rsData as New ADODB.Recordset
rsData.Open cmdProc,, adOpenStatic,adLockBatchOptimistic
'...Process recordset data.
Here is the solution:
If IsNull(objRevenueToday("REVENUE")) Then
RevenueToday = "0"
Else
RevenueToday = objRevenueToday("REVENUE")
End If
Not very ideal but fixed my error.
Assuming SQL Server (although similar techniques available in other DBs.
Change the query so that is will not return nulls in records. For example in the T-SQL
SELECT ISNULL(REVENUE, 0), .... FROM ....
Change the settings as below. It force the client side cursor...It worked for me
set pagedlistrs=CreateObject("adodb.recordset")
pagedlistrs.cursorlocation = 3 ' adUseClientpagedlistrs
pagedlistrs.Open SQL, objConn, 3,3,1

Resources