I am working with VB.Net. I have resolved a behavior where the code returns with an error of "Cannot access a disposed object. Object name: 'DataContext accessed after Dispose.'."
My problem : I simply don't understand why it works !
Here is my code when happens the error :
Public Function Element_Import(ByVal id_element As Integer) As elements
Using db As New GlobalDataContext(MyConnexion)
Return (From element In db.elements
Select element
Where element.id_element = id_element).First
End Using
End Function
Then I try to retreave the data :
Dim myElement As elements = _MyConnection.Element_Import(id_element)
Dim myLocal As List(Of elements_localisation) = myElement.elements_localisation.ToList '-- ObjectDisposedException !
When I import my element then try to access sub-tables called "elements_localisation" and "elements_files" an ObjectDisposedException occures. That's fair as the DataContext is not available.
So I have done something different :
Public Function Element_ImportContext(ByVal id_element As Integer) As elements
Dim myElement As elements
Dim myElementLocalisation As New List(Of elements_localisation)
Dim myElementFiles As New List(Of elements_files)
Using db As New GlobalDataContext(MyConnexion)
myElement = (From element In db.elements
Select element
Where element.id_element = id_element).First
myElementLocalisation = myElement.elements_localisation.ToList
myElementFiles = myElement.elements_files.ToList
End Using
Return myElement
End Function
Then I try to retreave the data :
Dim myElement As elements = _MyConnection.Element_ImportContext(id_element)
Dim myLocal As List(Of elements_localisation) = myElement.elements_localisation.ToList '-- IT WORKS !
I really wanna understand what happened as, in both case, the DataContext is disposed.
Can anyone explain ?
When you write LINQ, you write a query to be executed against some data, that query is only executed when another part of the code needs the data.
In your case, you are returning the myElement variable because you have used .First(), which forces the query to be executed and the first item to be returned.
The properties elements_localisation and elements_files are likely to be virtual properties that are only loaded when you request them. (This is certainly the case with Entity Framework, I'm not sure what you're using here).
Your program will try to access the virtual property which will then go off to the data context to get the next bit of data you requested, but in your case the data context is disposed.
Your second approach works because you have used ToList() on the virtual properties, which forces the data to be retrieved then and there, before your data context has been disposed.
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?
I'm in the process of switching my application from MSSQL to MYSQL. When I was using MSSQL, I retrieved the last auto increment value via
Private Sub dsImpoundInformation_Inserted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs) Handles dsImpoundInformation.Inserted
_impoundId = e.Command.Parameters("impoundId").Value
End Sub
Private Sub dsImpoundInformation_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs) Handles dsImpoundInformation.Inserting
Dim impoundIdparam As New SqlClient.SqlParameter()
impoundIdparam.ParameterName = "impoundId"
impoundIdparam.Direction = System.Data.ParameterDirection.Output
impoundIdparam.DbType = DbType.Int32
impoundIdparam.Value = 0
e.Command.Parameters.Add(impoundIdparam)
End Sub
and
InsertCommand="INSERT INTO LotManager_impounds (accountId, truckId, createdBy, driver, locationId, dateArrived, towedFrom, reasonForImpound, reasonForImpoundOther, impoundCity, impoundCounty, timeOfImpound, dateDeemedAbandoned, ticketNumber) VALUES (#accountId,#truckId,#createdBy,#driver,#locationId,#dateArrived,#towedFrom,#reasonForImpound,#reasonForImpoundOther,#impoundCity,#impoundCounty,#timeOfImpound,#dateDeemedAbandoned,#ticketNumber); SET #impoundId = SCOPE_IDENTITY();"
Now when i try
InsertCommand="INSERT INTO LotManager_impounds (accountId, truckId, createdBy, driver, locationId, dateArrived, towedFrom, reasonForImpound, reasonForImpoundOther, impoundCity, impoundCounty, timeOfImpound, dateDeemedAbandoned, ticketNumber) VALUES (#accountId,#truckId,#createdBy,#driver,#locationId,#dateArrived,#towedFrom,#reasonForImpound,#reasonForImpoundOther,#impoundCity,#impoundCounty,#timeOfImpound,#dateDeemedAbandoned,#ticketNumber); SET #impoundId = LAST_INSERT_ID();"
i get the error:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near '0 = LAST_INSERT_ID()' at line 1
And when i try:
InsertCommand="INSERT INTO LotManager_impounds (accountId, truckId, createdBy, driver, locationId, dateArrived, towedFrom, reasonForImpound, reasonForImpoundOther, impoundCity, impoundCounty, timeOfImpound, dateDeemedAbandoned, ticketNumber) VALUES (#accountId,#truckId,#createdBy,#driver,#locationId,#dateArrived,#towedFrom,#reasonForImpound,#reasonForImpoundOther,#impoundCity,#impoundCounty,#timeOfImpound,#dateDeemedAbandoned,#ticketNumber); SET impoundId = LAST_INSERT_ID();"
I get the error:
Unknown system variable 'impoundId'
ultimately, I'm just trying to get the last auto increment value but there are other sections of my code in other applications that I plan on switching to MYSQL that depend on output parameters. I have't yet explored using stored procedures but at this time I would like to get this to work in a similar fashion to how I had it with MSSQL.
Thanks in advance.
Finally I broke down and decided to use stored procedures. This is the best way to do it any ways and makes the code a lot cleaner. For anyone that's encountering this same problem my advice to you would be don't waste you time trying to make it work and just use a stored procedure.
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
I am trying to learn some VB.NET for my coo-op that starts next week, and for that reason i took my portfolio web site that is on C# and just started to converting it to VB.NET to get familiar with the syntax.
I am sure my problem is simple however i have a hard time solving it.
I am trying to grab data with the linq query and then return it as list to bind to the Repeater.
I have the following function:
Public Function getProjects() As List(Of portfolio_website)
Using myPortfolio As New PortfolioDataContext
Try
Dim myProjects = (From p In myPortfolio.portfolio_websites _
Order By p.website_id Descending _
Select New With {.name = p.website_name, .id = p.website_id}).Take(5)
Return myProjects
Catch ex As Exception
Return Nothing
End Try
End Using
End Function
However I am getting an error.
If i would do it in C# then myProjects will be var and in return i will have
return myProjects.ToList();
And it would work fine. However if I try to use ToList() in VB.NET i am getting error that it cannot convert it from ling to sql List to the generic list.
How do i do this convertion in VB.NET ? or maybe there is another way ?
I am decent when it comes to C# however somewhat lost with the VB.NET syntax.
I hate it.
Second after I asked my question i realized my mystake.
It is same as in C#, but if i take
Select New With {.name = p.website_name, .id = p.website_id
then i either need to have a custom object, or i need to take everything.
So i changed my linq to sql to the
Dim myProjects = (From p In myPortfolio.portfolio_websites _
Order By p.website_id Descending _
Select p).Take(5)
Return myProjects.ToList()
and now everything is working.