Variable is Not Available Using dbContexts? - asp.net

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.

Related

PDFs missing EOF section on customer's server

Folks- I'm relatively new to ASP.NET, and have a question that has stumped my peers-- folks much more experienced than myself.
My company created a website that uses iTextSharp to build and stream PDFs. The functionality works perfectly on my company's development and staging/test servers. The customer's functionality isn't working well, however. The customer's server streams a file where the PDF is missing the last block of data representing the EOF section. The PDF seems to build correctly, streams correctly, but when users open the PDF, the following error displays: 'There was an error opening this document. The file is damaged and could not be repaired.'
By comparing the PDFs in a text viewer (comparing the PDFs from my server vice the customer's server), I can see that the EOF section is missing from the customer's PDF. I'll also note that no errors are thrown during PDF creation, if that's helpful. To make matters more difficult, I have no access to the customer's servers, so I won't be able to interact with the systems directly.
The asp.net version is 3.5. Both of our servers (my company and the customer) are: running IIS7.5 on Server 2008R2; using iTextSharp is 5.1.2; and are configured for FIPS compatibility.
I've read dozens and dozens of posts detailing why a PDF isn't created properly, why it may not be streaming, and all things related, but I haven't seen this particular issue before. I guess what I need to know in the short-term is: 1) what can I provide to help diagnose the issue, 2) where is a good place to start looking for areas of concern?
Also, I updated to revision 5.5.3 last night; same results-- it works fine on my servers, but produces broken PDFs on the customer's server.
Code added:
Public Function BuildReport(ByVal tblReport As DataTable, _
ByRef memStream As MemoryStream, _
ByRef strErrMsg As String) As Boolean
Dim booOK As Boolean = True
strErrMsg = String.Empty
' Create document
Try
' Create writer (listens to the document and directs PDF stream)
memStream = New MemoryStream()
Dim msWriter As PdfWriter = PdfWriter.GetInstance(_document, memStream)
msWriter.CloseStream = False
'Create header
Dim ev As New itsEvents
msWriter.PageEvent = ev
' Set document metadata
_document.AddTitle(_strMetaTitle)
_document.AddSubject(_strMetaSubject)
_document.AddCreator(_strMetaApplication)
_document.AddAuthor(_strMetaAuthor)
' Open document, add document content, close document
_document.Open()
AddReportContent(tblReport)
_document.Close()
Catch ex As Exception
booOK = False
strErrMsg = ex.Message
End Try
Return booOK
End Function
Private Sub AddReportContent(ByVal tblReport As DataTable)
' Count report columns
Dim intReportColumns As Integer = 0
For Each col As DataColumn In tblReport.Columns
If ContainedInColumnMask(col.ColumnName) Then
intReportColumns += 1
End If
Next
' Build table
Dim table As PdfPTable
Dim cell As PdfPCell
Dim phrase As Phrase
If intReportColumns >= 1 Then
' Init table
table = New PdfPTable(intReportColumns)
' Add title to table
'phrase = New Phrase(_strMetaTitle, _fontLarge)
'cell = New PdfPCell(phrase)
'cell.Colspan = intReportColumns
'cell.HorizontalAlignment = 1 ' 0=Left, 1=Centre, 2=Right
'table.AddCell(cell)
' Add column headers to table
Dim i As Integer = 0
Dim intColWidth As Integer
Dim intColWidths As Integer() = New Integer(intReportColumns - 1) {}
Dim intColWidthTotal As Integer = 0
Dim strColName As String
For Each col As DataColumn In tblReport.Columns
If ContainedInColumnMask(col.ColumnName) Then
strColName = col.ColumnName
If (col.ExtendedProperties.Item("NOTEXTEXPORT") <> True) Then
If col.ExtendedProperties.Contains("FRIENDLYNAME") Then
strColName = col.ExtendedProperties.Item("FRIENDLYNAME")
End If
End If
phrase = New Phrase(strColName, _fontMedium)
cell = New PdfPCell(phrase)
cell.BorderWidth = 1
cell.BackgroundColor = iTextSharp.text.BaseColor.LIGHT_GRAY
'cell.BackgroundColor = iTextSharp.text.Color.LIGHT_GRAY
table.AddCell(cell)
intColWidth = GetColumnWidth(col, strColName, _fontMedium.Size, _fontSmall.Size)
intColWidths(i) = intColWidth
intColWidthTotal += intColWidth
i += 1
End If
Next
table.TotalWidth = intColWidthTotal
table.SetWidths(intColWidths)
' Add rows to table
For Each row As DataRow In tblReport.Rows
For Each col As DataColumn In tblReport.Columns
If ContainedInColumnMask(col.ColumnName) Then
phrase = New Phrase(SetBlankIfNothing(row.Item(col.ColumnName).ToString()), _fontSmall)
cell = New PdfPCell(phrase)
cell.BorderWidth = 0.5
table.AddCell(cell)
End If
Next
Next
Else
' Init table
table = New PdfPTable(1)
' Nothing to add to table
table.AddCell(String.Empty)
End If
' Add table to document
_document.Add(table)
End Sub
Public Sub New(ByVal strMetaTitle As String, _
ByVal strMetaSubject As String, _
ByVal strMetaApplication As String, _
ByVal strMetaAuthor As String, _
Optional ByVal strColumnMask As String = "")
GetStaticInfo()
_strMetaTitle = strMetaTitle
_strMetaSubject = strMetaSubject
_strMetaApplication = strMetaApplication
_strMetaAuthor = strMetaAuthor
_document = New iTextSharp.text.Document(_itsPage, _itsMarginLeft, _itsMarginRight, _itsMarginTop, _itsMarginBottom)
If strColumnMask <> "" And Not strColumnMask Is Nothing Then
_strColumnMask = strColumnMask
End If
End Sub
Public Sub New(ByVal strMetaTitle As String, _
ByVal strMetaSubject As String, _
ByVal strMetaApplication As String, _
ByVal strMetaAuthor As String, _
Optional ByVal strColumnMask As String = "")
GetStaticInfo()
_strMetaTitle = strMetaTitle
_strMetaSubject = strMetaSubject
_strMetaApplication = strMetaApplication
_strMetaAuthor = strMetaAuthor
_document = New iTextSharp.text.Document(_itsPage, _itsMarginLeft, _itsMarginRight, _itsMarginTop, _itsMarginBottom)
If strColumnMask <> "" And Not strColumnMask Is Nothing Then
_strColumnMask = strColumnMask
End If
End Sub

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

How to test a controller which updates what was posted to it

This seems really simple, but I can't seem to get it to work. I want to unit test my controller's assign action. It takes a IEnumerable(Of Integer) which represent the ID's of all the objects to assign.
Here's the code I've written, I'm getting an error on the Do statement (I copied the code from Ayende's blog here http://ayende.com/blog/3397/rhino-mocks-3-5-a-feature-to-be-proud-of-seamless-do).
<Test()> _
Public Sub Assign_Post_Should_Assign_All_Audits_Provided()
Dim auditsToAssign As IEnumerable(Of HvacAudit) = HvacAuditsGenerator.GenerateAudits() _
.Unassigned()
Dim auditIDs As IEnumerable(Of Integer) = auditsToAssign.Select(Function(audit, index) audit.HvacAuditID)
Dim hvacAuditRepo As IHvacAuditRepository = MockRepository.GenerateMock(Of IHvacAuditRepository)()
hvacAuditRepo.Stub(Sub(repo) repo.GetAuditByID(1)) _
.Do(Function(invocation) invocation.ReturnValue = auditsToAssign.Single(Function(audit) audit.HvacAuditID = invocation.Arguments(0)))
Dim controller As New HvacAuditController(hvacAuditRepo)
Dim r As ViewResult = controller.Assign(auditIDs).AssertViewRendered()
r.AssertAssignedAuditCount(auditsToAssign.Count)
auditsToAssign.AssertAreAssigned()
hvacAuditRepo.AssertWasCalled(Sub(h) h.SaveChanges())
End Sub
I was able to fix this by changing the code to use a function lambda instead of a sub lambda and return the value directly. I'm not sure what Ayende's blog was referring to.
<Test()> _
Public Sub Assign_Post_Should_Assign_All_Audits_Provided()
Dim auditsToAssign As IEnumerable(Of HvacAudit) = HvacAuditsGenerator.GenerateAudits() _
.Unassigned()
Dim auditIDs As IEnumerable(Of Integer) = auditsToAssign.Select(Function(audit, index) audit.HvacAuditID)
Dim hvacAuditRepo As IHvacAuditRepository = MockRepository.GenerateMock(Of IHvacAuditRepository)()
hvacAuditRepo.Stub(Sub(repo) repo.GetAuditByID(1)) _
.Do(Function(auditID as Integer) Return auditsToAssign.Single(Function(audit) audit.HvacAuditID = auditID))
Dim controller As New HvacAuditController(hvacAuditRepo)
Dim r As ViewResult = controller.Assign(auditIDs).AssertViewRendered()
r.AssertAssignedAuditCount(auditsToAssign.Count)
auditsToAssign.AssertAreAssigned()
hvacAuditRepo.AssertWasCalled(Sub(h) h.SaveChanges())
End Sub

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

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

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.

Resources