LINQ to Entities does not recognize the method - simple delete statement - asp.net

I have a GridView and on a row being deleted I trigger the GridView1_RowDeleting sub, but I receive an error "LINQ to Entities does not recognize the method 'System.Web.UI.WebControls.TableCell get_Item(Int32)' method, and this method cannot be translated into a store expression." Code is:
Private Sub GridView1_RowDeleting(sender As Object, e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles GridView1.RowDeleting
' The deletion of the individual row is automatically handled by the GridView.
Dim dbDelete As New pbu_housingEntities
' Remove individual from the bed.
Dim remove_bed = From p In dbDelete.Beds _
Where p.occupant = GridView1.Rows(e.RowIndex).Cells(3).Text _
Where p.room = GridView1.Rows(e.RowIndex).Cells(6).Text _
Where p.building = GridView1.Rows(e.RowIndex).Cells(5).Text _
Order By p.id Descending _
Select p
remove_bed.First.occupant = ""
dbDelete.SaveChanges()
' Increase number of open spaces in room.
Dim update_occupancy = From p In dbDelete.Rooms _
Where p.room1 = GridView1.Rows(e.RowIndex).Cells(6).Text
Where p.building = GridView1.Rows(e.RowIndex).Cells(5).Text _
Select p
update_occupancy.First.current_occupancy = update_occupancy.First.current_occupancy - 1
dbDelete.SaveChanges()
End Sub
The specific line erroring out is:
remove_bed.First.occupant = ""

That's because the Linq query is translated to SQL, and there is no way to translate GridView1.Rows(e.RowIndex).Cells(3).Text to SQL. You need to extract the values from the GridView, then use them in the query
Dim occupant As String = GridView1.Rows(e.RowIndex).Cells(3).Text
Dim room As String = GridView1.Rows(e.RowIndex).Cells(6).Text
Dim building As String = GridView1.Rows(e.RowIndex).Cells(5).Text
Dim remove_bed = From p In dbDelete.Beds _
Where p.occupant = occupant _
Where p.room = room _
Where p.building = building _
Order By p.id Descending _
Select p

You have to put those values in variables before executing the query, otherwise the Entity Provider will try to pull the whole object into the query and access it's properties when it is trying to translate it into a SQL statement - which fails since there is no SQL equivalent.

Related

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection when adding additional dropdownlist

I had the following code:
If Page.IsPostBack = False Then
' If prospect is coming from unique url
Dim prospect_url As String = Page.RouteData.Values("value")
' Save prospect_url into session variable
Session("prospect_url") = prospect_url
Using dbContext As IRFEntities = New IRFEntities
' Prepopulate the states dropdown.
Dim getStates = (From p In dbContext.IRF_States _
Order By p.name _
Select p)
ddlState.DataSource = getStates
ddlState.DataTextField = "name"
ddlState.DataValueField = "id"
ddlState.DataBind()
' Grab info. about prospect based on unique url.
Dim getProspect = (From p In dbContext.IRF_Prospects _
Where p.url = prospect_url _
Select p).FirstOrDefault
' If they have a record...
If getProspect IsNot Nothing Then
'If IsDBNull(getProspect.user_id) Then
If getProspect.user_id Is Nothing Then
' Prepopulate the form with their information.
' These must have a value, so we need to make sure that no column is null in the database.
txtFirst.Text = getProspect.first_name
txtLast.Text = getProspect.last_name
txtAddress.Text = getProspect.address
txtCity.Text = getProspect.city
ddlState.SelectedValue = getProspect.state
txtZip.Text = getProspect.zip
txtPhone.Text = getProspect.phone
txtEmail.Text = getProspect.email_address
txtYearEnrolling.Text = getProspect.enrolling_in
Else
' Redirect them to login.
Response.Redirect("login.aspx")
End If
End If
End Using
End If
I then added directly below ddlState.DataBind() the following:
' Prepopulate the programs dropdown.
Dim getPrograms = (From p In dbContext.IRF_Program _
Order By p.name _
Select p)
ddlProgram.DataSource = getPrograms
ddlProgram.DataTextField = "name"
ddlProgram.DataValueField = "id"
ddlState.DataBind()
Now I get the error:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection
If I comment out the inserted code, the code works. Why is this code causing a problem?
You have lost this object:
dbContext
That is the resources (including the connection operations) for this object have already been disposed of and cleaned up. You can re-create the object if you need to databind another drop down list.
Dim dbContext as IRFEntities=Nothing
Using dbContext= New IRFEntities
//perform first databind
End Using
Using dbContext = New IRFEntities
//code to perform second databind
End Using

SqlCommand placeholder parameters: "Incorrect syntax near '?'" and "Must declare the scalar variable #param"?

I am developing a web mapping application intranet for our company. I am creating an "add polygon" function on the map. I use AspMap, VB.NET and SQL Server. When a user clicks a button to add a new record from the web form input data attribute, the error Incorrect syntax near '?' occurs.
My code is:
Private Sub AddNewShape(ByVal checklist_id As String, ByVal type As String, ByVal shape As AspMap.Shape, ByVal address_area As String, ByVal dmz As String, ByVal customerid As String, ByVal source As String, ByVal area As String, ByVal instalatur As String, ByVal developer As String, ByVal data_received As DateTime, ByVal doc_data As DateTime, ByVal datereport As DateTime, ByVal remark As String)
Dim tableName As String
Select Case shape.ShapeType
Case AspMap.ShapeType.Line
tableName = "lines"
Case AspMap.ShapeType.Polygon
tableName = "sambungan_baru"
Case Else
Return
End Select
Dim conn As SqlConnection = GetDbConnection()
Dim sql As String = "INSERT INTO " & tableName & " (CHECKLIST_ID, TYPE, SHAPEDATA, ADDRESS_AREA, DMZ, CUSTOMERID, SOURCE, AREA, INSTALATUR, DEVELOPER, DATA_RECEIVED, DOC_DATA, DATA_SENT, REMARK) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
Dim cmd As SqlCommand = New SqlCommand(sql, conn)
cmd.Parameters.AddWithValue("CHECKLIST_ID", checklist_id)
cmd.Parameters.AddWithValue("TYPE", type)
cmd.Parameters.AddWithValue("SHAPEDATA", shape.ShapeData)
cmd.Parameters.AddWithValue("ADDRESS_AREA", address_area)
cmd.Parameters.AddWithValue("DMZ", dmz)
cmd.Parameters.AddWithValue("CUSTOMERID", customerid)
cmd.Parameters.AddWithValue("SOURCE", source)
cmd.Parameters.AddWithValue("AREA", area)
cmd.Parameters.AddWithValue("INSTALATUR", instalatur)
cmd.Parameters.AddWithValue("DEVELOPER", developer)
cmd.Parameters.AddWithValue("DATA_RECEIVED", data_received)
cmd.Parameters.AddWithValue("DOC_DATA", doc_data)
cmd.Parameters.AddWithValue("DATA_SENT", datereport)
cmd.Parameters.AddWithValue("REMARK", remark)
cmd.ExecuteNonQuery()
conn.Close()
ReloadShapesDatabase()
End Sub
I changed this:
Dim sql As String = "INSERT INTO " & tableName & " (CHECKLIST_ID, TYPE, SHAPEDATA, ADDRESS_AREA, DMZ, CUSTOMERID, SOURCE, AREA, INSTALATUR, DEVELOPER, DATA_RECEIVED, DOC_DATA, DATA_SENT, REMARK) VALUES *(?,?,?,?,?,?,?,?,?,?,?,?,?,?)
to this:
Dim sql As String = "INSERT INTO " & tableName & " (CHECKLIST_ID, TYPE, SHAPEDATA, ADDRESS_AREA, MZ, CUSTOMERID, SOURCE, AREA, INSTALATUR, DEVELOPER, DATA_RECEIVED, DOC_DATA, DATA_SENT, REMARK)(#checklist_id, #type, #shapedata, #address_area, #dmz, #conection, #source, #area, #instalatur, #developer, #data_received, #doc_data, data_sent, #remark)"
And I run into the alert: Must declare the scalar variable "#conection". Can anyone help me?
You are confusing two different styles of parameters in SQL queries. The ODBC syntax uses simple placeholder '?' character for each parameter, and the parameters are replaced in the same order that you add them to the parameters collection. For an OdbcCommand, the name you give the parameters is ignored, and only their sequence matters.
For a SqlCommand, the parameter names are meaningful; when the command executes, it will be run through a SQL Stored procedure that takes a list of parameter names and values and substitutes them into the T-SQL query. In this case, the order you add parameters to your query isn't important, but you need to make sure the names are correct (including the "#" prefix.)
The proper way to use a SqlCommand with parameters is as follows:
// The SQL Query: Note the use of named parameters of the form
// #ParameterName1, #ParameterName2, etc.
Dim sql As String = "INSERT INTO " & tableName & _
" (CHECKLIST_ID, TYPE, SHAPEDATA ) " & _
"VALUES " & _
" (#ChecklistId, #Type, #ShapeData )"
// The Parameter List. Note that the Parameter name must exactly match
// what you use in the query:
Dim cmd As SqlCommand = New SqlCommand(sql, conn)
cmd.Parameters.AddWithValue("#CheckListId", checklist_id)
cmd.Parameters.AddWithValue("#Type", type)
cmd.Parameters.AddWithValue("#ShapeData", shape.ShapeData)
cmd.ExecuteNonQuery()
You should assign parameters like this and in your case you missed providing value for "CONECTION" parameter. Also as an additional note, you should always enclose connection objects in using blocks. See this and look at the "Remarks" section.
command.CommandText = "INSERT INTO Table (Col1, Col2, Col3) VALUES _
(#Col1Val, #Col2Val, #Col3Val)"
command.Parameters.AddWithValue("#Col1Val","1");
command.Parameters.AddWithValue("#Col2Val","2");
command.Parameters.AddWithValue("#Col3Val","3");
Please make sure that Dim cmd As SqlCommand = New SqlCommand(sql, conn) uses conn with an open connection.
Then verify your parameters type to be in accordance with the database table definition. Plus, If your using string type you may add an ' before and after any text inserted.
To be sure, you can break on cmd.ExecuteNonQuery() and copy the value of the command associated and running it to any SQL manager tool.
Finally, dispose your cmd.
Otherwise check if this is helpful for your issue : http://social.msdn.microsoft.com/Forums/en-US/sqlspatial/thread/9d75106a-b0d4-49cc-ac86-d41cba4ab797

Using Results Outside of dbContext in VB.NET

Lets say I have code like this:
Using dbContext as mydb_entities = New mydb_entities
Dim qperson = (From p in dbContext.People _
Where p.name = "John" _
Select p)
End Using
Using dbContext as yourdb_entities = New yourdb_entities
Dim qyou = (From p in dbContext.Customer _
Where p.name = "John" _
Select p)
End Using
How can I compare the results of qperson to qyou? Since the results "disappear" once End Using is executed?
You will need to declare both variables outside the using statements
Dim qperson As IQueryable(Of Person)
Dim qyou As IQueryable(Of Customer)
Using dbContext as mydb_entities = New mydb_entities
qperson = (From p in dbContext.People _
Where p.name = "John" _
Select p)
End Using
Using dbContext as yourdb_entities = New yourdb_entities
qyou = (From p in dbContext.Customer _
Where p.name = "John" _
Select p)
End Using
The key thing here is to know when your LINQ queries are going to get run. When this line of code is executed:
qperson = (From p in dbContext.People _
Where p.name = "John" _
Select p)
no query is sent to the server. Instead you get back an object that implements the IQueryable(Of T) interface that describes what the query is. The query isn't actually sent to the server and executed until you start to use the results, such as in a For Each loop. This is called delayed execution and is fundamental to LINQ.
So what does this mean to you? Well, it means that the context must not be disposed before you execute the query. In the examples so far this is not necessarily always true. (The nested answer might do so, depending what is actually happening inside the nested usings.)
The typical way to deal with this is to force execution of the query to produce an in-memory collection of the results before the context is disposed. The ToList() extension method is a common way to do this. So, for example:
Dim qperson As IList(Of Person)
Dim qyou As IList(Of Customer)
Using dbContext as mydb_entities = New mydb_entities
qperson = (From p in dbContext.People _
Where p.name = "John" _
Select p).ToList()
End Using
Using dbContext as yourdb_entities = New yourdb_entities
qyou = (From p in dbContext.Customer _
Where p.name = "John" _
Select p).ToList()
End Using
Now you have executed the queries and got the results into memory before the contexts are disposed and you can happily do what you want with them.
In C# I just typically nest the usings...
using (var context blahentities())
{
using (var context2 blahentities())
{
}
}
Check this out for nesting usings in vb...
Nested using statements

Variable is Not Available Using dbContexts?

I have the following code that throws an error on the call for getOccupants within Using dbPC. Is there a way to make this value accessible in Using dbPC? Or a better way to accomplish this? I tried nesting Using dbPC inside of Using dbContext, but that also throws errors.
Protected Sub btnPushSemester_Click(sender As Object, e As EventArgs) Handles btnPushSemester.Click
Dim dbPC As New Campus6Entities
Dim dbContext As New pbu_housingEntities
Using dbContext
Dim get_Year = From p In dbContext.Configs _
Where p.Description = "year" _
Select p
Dim get_Term = From p In dbContext.Configs _
Where p.Description = "term" _
Select p
Dim thisYear = get_Year.First.textValue
Dim thisTerm = get_Term.First.textValue
Dim getOccupants = From p In dbContext.Residents _
Where p.semester = thisTerm _
Where p.year = thisYear _
Select p
End Using
Using dbPC
For Each row In getOccupants
Dim student_info = row
Dim PCstudent = From r In dbPC.RESIDENCies _
Where student_info.people_code_id = r.PEOPLE_ID _
Where r.ACADEMIC_YEAR = thisYear _
Where r.ACADEMIC_TERM = thisTerm _
Select r
For Each row2 In PCstudent
Dim student_info2 = row2
student_info2.DORM_BUILDING = student_info.Building1.building_code
student_info2.DORM_ROOM = student_info.Room1.room1
student_info2.RESIDENT_COMMUTER = "R"
student_info2.DORM_CAMPUS = "O000000001"
dbPC.SaveChanges()
Next
Next
End Using
End Sub
Because of deferred execution, the query is not actually executed until you iterate over the collection, but by that time, you have already disposed the dbContext object. Try enclosing all the code in the Using blocks:
Using dbPC As New Campus6Entities
Using dbContext As New pbu_housingEntities
'rest of code here
End Using
End Using
Declare getOccupants outside of the using block. You can assign it inside the block, but you have to declare it outside or it goes out of scope before you actually need to use it.

Select query in LINQ based on Foreign Table

I have 2 Tables , OrderDetails and Requests In my LINQ to SQL dbml file.
OrderDetailsID is a foreign key in Requests Table.
I want to write the query to get the sum of UnitCost from OrderDetails based on OrderId.
And If there is a row in Requests Table for each OrderDetailsID, and the Requests.Last.RequestType="Refund" I want to reduce the total refund amount from the main sum otherwise If there is no row based on OrderDetailsID, add to sum.
Here is the way I implement that.
I am looking to prevent using "For each".
Any Solutions?
iRefund = (From od1 In dc.OrderDetails _
Where od1.OrderID =1 _
Select od1.UnitCost).Sum
Dim objOrderDetails = (From od1 In dc.OrderDetails _
Where od1.OrderID =1 _
Select od1)
For Each OrderDetail As ORM.Entities.OrderDetail In objOrderDetails
If Not OrderDetail.Requests Is Nothing Then
IF OrderDetail.Requests.Last.RequestType="Refund" Then
iRefund -= OrderDetail.UnitCost
End If
End If
Next
If you want to use Linq instead of a for-each loop, you could use the ForEach extension method of List:
Dim objOrderDetails = (From od1 In dc.OrderDetails _
Where od1.OrderId = 1 _
Select od1).ToList()
objOrderDetails.ForEach(AddressOf DecrementAmount)
Private Sub DecrementAmount(ByVal d As OrderDetail)
If d.Requests IsNot Nothing _
AndAlso d.Requests.Count > 0 _
AndAlso d.Requests.Last.RequestType = "Refund" Then
iRefund -= d.UnitCost
End If
End Sub
This assumes that iRefund is a module variable.

Resources