Online Test using ASP.NET / Linq - asp.net

Working on a Online Test.
I have 3 tables
Questions
Subject
Topic
I have made a stored procedure which returns 25 random records. I want to store it in-memory and then display 1 question at a time with AJAX. I don't want to hit database 25 times as there are many users, I tried and store the result in viewstate but then I am not able to cast it back. if I use
Dim qus = from viewstate("questions")
it works, but it doesn't work when I retrieve 1 record at a time.
Code:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
ViewState.Add("QuestionNo", 0)
Dim qus = From q In PML.PM_SelectRandomQuestionFM Select q
viewstate.add("questions",qus)
LoadQuestion(0)
End If
End Sub
Private Sub LoadQuestion(ByVal i As Integer)
Dim QuestionNo As Integer = CType(ViewState("QuestionNo"), Integer) + 1
Try
If QuestionNo <= 25 Then
Dim qus = viewstate("questions")
Me._subjectTopic.Text = String.Format("<b>Subject:</b> {0} -- <b>Topic:</b> {1}", qus(i).subjectName, qus(i).TopicName)
Me._question.Text = " " & qus(i).Question
Me._answer1.Text = " " & qus(i).Answer1
Me._answer2.Text = " " & qus(i).Answer2
Me._answer3.Text = " " & qus(i).Answer3
Me._answer4.Text = " " & qus(i).Answer4
Me._questionNo.Text = String.Format("Question No. {0} / 25", QuestionNo)
ViewState.Add("QuestionNo", QuestionNo)
Else
Server.Transfer("freeMemberResult.aspx")
End If
Catch ex As Exception
Throw New System.Exception(ex.ToString)
End Try
End Sub
I tried casting the object to
Dim qus = CType(ViewState("questions"), IQueryable(Of PM_SelectRandomQuestionFMResult))
but then I get this error
System.Linq.Enumerable+WhereSelectEnumerableIterator`2
Please HELP or if there is any other method to do it, if my method of doing online test is wrong.
Regards

IMO, you're over-engineering this. Why screw around trying to hold the data in memory? Why not write each question to a div, and then hide all of the question divs except for the "current question".
Much easier to implement and you're not hitting the server with several AJAX calls, This also make saving state (previously answered questions, etc) much, much easier.

Have you tried just using Session to maintain state? Is there a requirement that prohibits you from doing this?
Dim qus = CType(Me.Session("questions"), IQueryable(Of PM_SelectRandomQuestionFMResult))

Related

Display data of the field in a Label using Function

I have around 14 pages with 6-10 questions on each which are all
true and false answers, Written to the DB as 1 and 0.
I have created
a summary page so it is printable which contains all 14 pages with all 6-10
questions on each then I want to display the answer by the question via a
Label
I am very bad at VB.net and SQL so any help on this would be
great
I managed to get the first one working, to display as "Yes or No"
but the second one doesn't work
Is anyone able to
formulate a function so I can just call a single line of code for each label
instead of having a ton of if statements?
I'm super bad at sql and vb
and have hardly any experience so any help will be appreciated.
This is
the code I currently have, Please edit as needed (if its even right?)
Imports System.Data
Imports System.Data.SqlClient
Public Class DraftPrint
Inherits System.Web.UI.Page
Dim con As New SqlConnection
Dim comm_Id As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
comm_Id = Request.QueryString("Comm").ToString
con.ConnectionString = "Data Source=YK15-YKC0201;Initial Catalog=Testing;Integrated Security=true"
con.Open()
Dim cmd As New SqlCommand
cmd.Connection = con
Dim str As String = "Select Indicator, Question, Answer From maca where community_ID =" + comm_Id.ToString + " order by Indicator ASC"
Dim adapter As SqlDataAdapter = New SqlDataAdapter(str, con)
Dim dt_summary As DataTable = New DataTable
adapter.Fill(dt_summary)
Dim indicator As Integer = dt_summary.Rows(0)(0)
Dim question As Integer = dt_summary.Rows(0)(1)
Dim answer As String = dt_summary.Rows(0)(2)
If question = 1 And answer = False Then
DraftPrint1.Text = "No"
Else
DraftPrint1.Text = "Yep"
End If
If indicator = 1 And question = 2 And answer = False Then
DraftPrint2.Text = "No"
Else
DraftPrint2.Text = "Yep"
End If
This is just one of the ways to solve it. You can prepare everything in the query as:
Select Indicator, Question,
CASE
WHEN Answer = 1 And Indicator = 1 THEN "Yes" /* Not sure what indicator is but lets pretend it must be 1 for success */
ELSE "No"
END as Answer
FROM
...
Now, one of the way to map it in code is to Order By Question (assuming question number)
DraftPrint1.Text = dt.rows(1-1)("Answer").ToString()
DraftPrint2.Text = dt.rows(2-1)("Answer").ToString()
......
As you see, this way everything comes from DB ready to populate your label, so all you have to do is to map right row to right label. To avoid confusion I use (1-1) technique. You could also do dynamic control creation based on your query resultset - this way you wouldn't need to know numbers of your controls upfront.

Select Query on Access Database in Visual Studio

heres my code :
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
ltRooms.Text = CInt(Session("numOfRooms"))
'Calculate total cost
Dim intPrice As Integer
Dim intTotal As Integer
intPrice = AccessDataSource1.SelectCommand = "SELECT [Price] FROM [Rooms] WHERE ([RoomType] = 'RoomType')"
intTotal = intPrice * intRooms
ltPrice.Text = intTotal.ToString
End Sub
and my datasource
<asp:AccessDataSource ID="AccessDataSource1" runat="server"
DataFile="Hostel.accdb"
SelectCommand="SELECT * FROM [Bookings]"></asp:AccessDataSource>
I'm trying to store the value from the select query and then use it to work out the total price and then store it in a literal. So far I am only getting 0. No compile errors.
Does anyone one know why this isn't working?
I am consolidating the various comments into an answer for clarity and to stop the page complaining about extended discussion. This is all off the top of my head so there might be some errors in the code. It should be enough to pinpoint the problem though.
Firstly, now that I look at it again today, I think your code is just setting the SelectCommand property of the data source and not actually querying the database. I think you need to use the DataSource.Select method.
Your code might end up looking something like this:
AccessDataSource1.SelectCommand = "SELECT [Price] FROM [Rooms] WHERE ([RoomType] = '" & RoomType & "')"
Dim intPrices As List(Of Integer) = AccessDataSource1.Select(DataSourceSelectArguments.Empty)
' Now do stuff with your price data.
If the above doesn't help then I would check the value of intPrice returned by the Select call. You should also check that RoomType is set correctly.
If the wrong data is coming back from the database then you should be able to fix your SQL query to retrieve the correct data. If you need further assistance with this then please post the SQL query and the table structure.
If the correct data is coming back then check where intRooms is defined. If it is zero then your total will be calculated as zero regardless of the value of intPrice.

Attempting to create shopping cart remove button

Note: This code actually codes from a tutorial book I'm reading at the moment, so you can imagine this is frustrating me greatly! I'm building a basic shopping cart, using VB.NET 4, Visual Studio 2010 and MS SQL Server R2 2008. The code below is supposed to remove items from the cart, by reading a session variable, editing it to remove the appropriate ProductID and return the amending string to the session variable. It is then supposed to rebind the data to the gridview (gvCart) to refresh the data...but it seems here there is an error.
Every time I build the site in Visual Studio, it validates fine. But every time I run the site, and attempt to use the remove button it gives me the error:
Incorrect syntax near ')'.
with the IDE pointing me toward the final parenthesis.
I have been pulling my hair out at this for a good 4 hours now, any advice appreciated!
Protected Sub gvCart_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles gvCart.SelectedIndexChanged
'This method is hooked to the Remove button & is removing items from the cart
Dim strProductId As String = gvCart.SelectedRow.Cells(1).Text
If Session("Cart") IsNot Nothing Then
'Remove selected ProductID from Session string and retrieve session string
Dim strCart As String = Session("Cart").ToString()
Dim arIDs As String() = strCart.Split(",")
'Iterate through ID's in the 'Cart' array and rebuild the string leaving out the selected ID
strCart = String.Empty
For Each str As String In arIDs
'use Trim to remove leading and trailing spaces
If str.Trim() <> strProductId.Trim() Then
strCart += str + ", "
End If
Next
'Remove trailing space and comma
If strCart.Length > 1 Then
strCart = strCart.Trim()
strCart = strCart.Substring(0, strCart.Length - 1)
End If
'Put back into session var
Session("Cart") = strCart
'Rebind gvCart, which forces the sqldatasource to requery
gvCart.DataBind()
End If
End Sub
[EDIT]
I am also including the code that runs for the event sqlCart_Selecting for completion sake:
Protected Sub sqlCart_Selecting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceSelectingEventArgs) Handles sqlCart.Selecting
Trace.Warn("sqlCart_Selecting") 'aids debugging
Dim strCart As String = String.Empty
If Session("Cart") IsNot Nothing Then
strCart = Session("Cart").ToString
e.Command.CommandText &= " WHERE product.ProductID IN (" + strCart + ") AND culture.CultureID = 'en'"
Else
e.Cancel = True
End If
End Sub
[EDIT]
Also including the SQL query used by the gridview 'gvCart' and the code for displaying the carts contents on another page
<asp:SqlDataSource ID="sqlCart" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT product.ProductID, product.Name, product.ProductNumber, product.Color, subcat.Name AS SubcategoryName, cat.Name AS CategoryName, description.Description FROM Production.Product product JOIN Production.ProductSubcategory subcat ON product.ProductSubcategoryID = subcat.ProductSubcategoryID JOIN Production.ProductCategory cat ON subcat.ProductCategoryID = cat.ProductCategoryID JOIN Production.ProductModel model on product.ProductModelID = model.ProductModelID JOIN Production.ProductModelProductDescriptionCulture culture ON model.ProductModelID = culture.ProductModelID JOIN Production.ProductDescription description ON culture.ProductDescriptionID = description.ProductDescriptionID"></asp:SqlDataSource>
Protected Sub btnAddToCart_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddToCart.Click
'The contents of the cart will be saved in a Session object as a string of coma-delimited values of ProductID's
Dim strCart As String = String.Empty
Dim strProductID As String = gvProducts.SelectedDataKey.Value.ToString()
If Session("Cart") Is Nothing Then
strCart = strProductID
Else
strCart = Session("Cart").ToString() + ", " + strProductID
End If
Session("Cart") = strCart
lblCart.Text = strCart
End Sub
I will take a shot here, since you are not showing us everything (the SQL query for instance).
But it feels like the SQL query is using IN clause. And it appears to be failing when the cart goes empty.
Since Session("Cart") contains the comma separated values of the product IDs, an empty list would make the following SQL query fail:
select id, name
from products
where id in ()
with the message:
Incorrect syntax near ')'.
You have to show us the portion of code that's reloading the query from Session("Cart"). The query should be reassembled.
But there's one trick you can use! If your product ids are numeric and always greater than zero, change this line:
strCart = String.Empty
to this:
strCart = '-1, '
Update
I will really teach how to fish on this one. :) the problem is here:
Dim strCart As String = String.Empty
If Session("Cart") IsNot Nothing Then
strCart = Session("Cart").ToString
e.Command.CommandText &= " WHERE product.ProductID IN (" + strCart + ") AND culture.CultureID = 'en'"
Else
e.Cancel = True
End If
When cart is empty, Session("Cart") is not Nothing but it's an empty string (provided that you removed the -1 workaround). If Session("Cart") is an empty string the where clause should be " WHERE culture.CultureID = 'en'" only, no mention to product ids. God speed!

Problem calling a stored procedure from VB.NET

I am pretty new to VB and I am not sure why this is not working, basically I am trying to run a stored procedure from my web code. The sp runs just fine in SQL, I've tried it several times so I am sure that is not the problem. I don't want to return any results, I just want to see an "ok" statement if it runs and an error message if it doesn't. The code I am using for the lables (warnings and confirmation) is reused from earlier on the same page, the same goes for the validations (valUpload). I am sure the solution is simple...
Protected Sub RunValidation_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles RunValidation.Click
Try
Dim bl As New BL.ORG
Dim db As Database = DatabaseFactory.CreateDatabase("MyConnection")
Dim dbCommand As DbCommand
db = DatabaseFactory.CreateDatabase("MyConnection")
dbCommand = db.GetStoredProcCommand("Company.dbo.uspMyStoredProcedure")
dbCommand.CommandTimeout = 300
db.AddInParameter(dbCommand, "ClientID", DbType.String, ddlCompany.SelectedValue)
db.AddInParameter(dbCommand, "startPeriod", DbType.String, ddlStartPeriod.SelectedValue)
db.ExecuteDataSet(dbCommand)
lblWarning.Text = "Please confirm that the <strong>ClientID and startPeriod </strong> are populated in the dropdown list."
lblWarning.Visible = True
lblConfirmation.Visible = False
Catch ex As Exception
valUpload.ErrorMessage = "There has been an unexpected error generating the page<br>(" + Err.Description + ")"
valUpload.IsValid = False
End Try
End Sub
I think the issue here is the line
db.ExecuteDataSet(dbCommand)
From what I can see, the command you want to run is
db.ExecuteNonQuery(dbCommand)
Here is an example site. The code is in C# but I think you can get the basic understanding of it. You could also use a translator on it if you really needed to.
http://msdn.microsoft.com/en-us/magazine/cc188702.aspx#S2
I would rewrite it to something similar to this:
Protected Sub RunValidation_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles RunValidation.Click
Using cnn As New SqlClient.SqlConnection("MyConnection")
cnn.Open()
Using cmd As New SqlClient.SqlCommand("Company.dbo.uspMyStoredProcedure", cnn)
cmd.CommandTimeout = 30
cmd.Parameters.Add(New SqlClient.SqlParameter("ClientID", SqlDbType.NVarChar, 50) With {.Value = ddlCompany.SelectedValue})
cmd.Parameters.Add(New SqlClient.SqlParameter("startPeriod", SqlDbType.NVarChar, 50) With {.Value = ddlStartPeriod.SelectedValue})
Try
cmd.ExecuteNonQuery()
Catch ex As Exception
valUpload.ErrorMessage = "There has been an unexpected error generating the page<br>(" + Err.Description + ")"
valUpload.IsValid = False
End Try
lblWarning.Text = "Please confirm that the <strong>ClientID and startPeriod </strong> are populated in the dropdown list."
lblWarning.Visible = True
lblConfirmation.Visible = False
End Using
End Using
End Sub
A few notes:
Wrap as little code as possible in a try-catch. In this case, only the database should be a cause of concern (granted you validated the inputs).
The using statement very neatly disposes your connection and command objects in case of problems.
You probably want to refactor the code even futher, keeping the database-calling section in a separate function/sub, and setting labels and UI messages somewhere else.

Entity Framework: Create Change History

I have a EDM (phoneDB) that models a back-end MSSQL database. I've developed a ASP.NET (VB) application that allows one to edit the information in this database. When someone edits a record entry I'd like to record this action.
Right now, I'm doing the following:
For Each..Next that checks whether entry is an object that has had its entitystate modified.
And If Not..End If that ensures we aren't dealing with a relationship entity or a null entity.
Now this is where it gets fuzzy. What I want to do is grab the information from these modified objects and record them into the database. Now I have something like this:
Dim audit as History
audit.action = "Changed information in " & propName & " to " & entry.CurrentValues(propName) & " from " & entry.OriginalValues(propName)
audit.action_by = this_user
audit.action_date = Date.Now
audit.extension_id =
I'm not sure, however, how to tell it to pull a specific property from entry. For example, I need to get (pseudo-code) something like:
audit.extension_id = entry.OriginalValues(extension_id)
I don't understand what do you mean by "pulling a specific property from an entry"? The (pseudo) code you wrote is not telling much, what is an extesion_id in your case? If extension_id is a property name of an entity, then you obtain it's original value by calling entry.OriginalValues("extension_id"), but I'm fairly sure you knew that.
Btw, you can do intricate history recording in the DB itself using triggers without the data layer even knowing it. It's a fairly old trick and works fast, see this
Here is how I accomplished it in the end:
Private Shared Sub context_SavingChanges(ByVal sender As Object, ByVal e As EventArgs)
' This allows us to record a history of the changes made by the user to the database. The record is created automatically by EF, but we need to save it to the database
' for permanent retention.
For Each entry As ObjectStateEntry In DirectCast(sender, ObjectContext).ObjectStateManager.GetObjectStateEntries(EntityState.Modified)
If Not entry.IsRelationship And entry.Entity IsNot Nothing Then
For Each propName As String In entry.GetModifiedProperties()
Dim context As New AppsEntities()
Dim audit As New History
audit.action_note = "Changed information in " & propName & " to " & entry.CurrentValues(propName) & " from " & entry.OriginalValues(propName)
audit.action_by = CStr(HttpContext.Current.Session("person_name"))
audit.action_date = Date.Now
audit.extension_id = entry.CurrentValues.GetValue(0)
context.AddToHistories(audit)
context.SaveChanges()
Next
End If
Next
End Sub

Resources