I create a question pool from where I choose random question to apply some algorithm, anyway when I debug the program I get Index was outside the bounds of the array error.
to have a clear idea about what I am talking about, here is my class for question:
Firstly I define class Gene represent question
public class Gene
{
public string question { get; set; }
public string CLO { get; set; }
public string type { get; set; }
public string Answer { get; set; }
public string mark { get; set; }
public string chapter { get; set; }
public Gene(string s, string t, string i, string a, string m, string c)
{
this.question = s;
this.type = t;
this.CLO = i;
this.Answer = a;
this.mark = m;
this.chapter = c;
}
}
List<Gene> QuestionList = new List<Gene>();
then I bring question from database
protected void DropDownList5_SelectedIndexChanged(object sender, EventArgs e)
{
string sub = DropDownList5.Text;
SqlConnection con = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Sondos\Downloads\For the project\suz\ExamGenerationSystem.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True");
string s = "select * FROM QuestionBank WHERE (Cource_Code = '" + DropDownList5.SelectedItem.Text + "') ORDER BY RAND()";
SqlCommand cmd = new SqlCommand(s, con);
SqlDataReader dr;
con.Open();
dr = cmd.ExecuteReader();
dr.Read();
while (dr.Read())
{
string ques = dr["Question"].ToString();
string questype = dr["Question_Type"].ToString();
string quesCLO = dr["CLO"].ToString();
string quesAnswer = dr["Answer"].ToString();
string quesMark = dr["Mark"].ToString();
string quesChapter = dr["Chapter"].ToString();
QuestionList.Add(new Gene(ques, questype, quesCLO, quesAnswer, quesMark, quesChapter));
}
}
then I make the question Pool
Gene[] QuestionPool { get { return QuestionList.ToArray(); } }
and when I try to choose question randomly using this :
private System.Random randome;
private Gene GetRandomQuestion()
{
int i = randome.Next(QuestionPool.Length);
return QuestionPool[i];
}
the error Index was outside the bounds of the array was in line
return QuestionPool[i];
int i = randome.Next(QuestionPool.Length);
Here if QuestionPool is empty, then this becomes int i = randome.Next(0) which returns zero.
Therefore,
return QuestionPool[i]; // Where i becomes 0
Will throw Index was outside the bounds as QuestionPool is empty and doesn't have anything at index 0.
So make sure that QuestionPool is not empty.
Some of the situations which will lead to QuestionPool being empty.
No record in database which has Cource_Code = DropDownList5.SelectedItem.Text
In this case while (dr.Read()) will be false on the first iteration and no Gene will be added to QuestionList.
GetRandomQuestion is called before any Gene is added to QuestionList
Avoiding SQL Injection
This line is vulnerable to SQL Injection
(Cource_Code = '" + DropDownList5.SelectedItem.Text + "')
This means that if a user changes the SelectedItem's Text to something like
a'); Drop table QuestionBank; -- //Anything after -- becomes a comment
Then the query will become
select * FROM QuestionBank WHERE (Cource_Code = 'a'); Drop table QuestionBank;
And your table will be dropped.
To avoid this please refer to this answer.
Lists as Arrays
When you have lists, then you can also access its items by index. And to get its length you can use Count. Thus, GetRandomQuestion can become
private Gene GetRandomQuestion()
{
int i = randome.Next(QuestionList.Count);
return QuestionList[i];
}
And you won't require the QuestionPool, provided that you're using it only for this purpose.
You just missed instantiate randome before you reference it.
private System.Random randome;
private Gene GetRandomQuestion()
{
randome = new System.Random // here
int i = randome.Next(QuestionPool.Length);
return QuestionPool[i];
}
Related
I have created the class at the bottom in c#. This class is referenced by webservices to determine user accesses, like this:
[WebMethod]
public List<FAFSA> getFAFSA(string pageID)
{
formValues fv = new formValues();
string personID = fv.personID;
List<FAFSA> lf = new List<FAFSA>();
if (fv.secBlur == "no_secBlur")
{
FAFSA f = new FAFSA();
f.fafsaCheck = "0";
lf.Add(f);
}
...
}
I'm trying to add the two variables fafsa and staff. The method getSecBlur() is returning all three values from my database for secBlur, fafsa, and staff. So how do I set up this class, so that the SecBlur method is only called once but populates all three of my variables so that they can be used in webservice calls? It will not work the way it is now because it says fafsa and staff need to be static, but if I make them static, then in the webservices it says that the members must be accessed with an instance reference.
Sorry if this isn't worded to well, but I'm new to this and still trying to learn...
public class formValues : System.Web.Services.WebService
{
public string userName = getUserName();
public string firstName = getFirstName();
public string personID = getPersonID();
public int fafsa = 0;
public int staff = 0;
public string secBlur = getSecBlur();
private static string getUserDataString(int ix)
{
string retValue = "";
if (HttpContext.Current.Request.IsAuthenticated)
{
HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
if (ticket != null)
{
string[] userData = { "" };
char[] delimiterChar = { '|' };
userData = ticket.UserData.Split(delimiterChar);
if (userData.Length > 1)
retValue = userData[ix];
else
{
FormsAuthentication.SignOut();
string redirUrl = "/DMC/loginNotFound.html";
HttpContext.Current.Response.Redirect(redirUrl, false);
}
}
}
}
return retValue;
}
private static string getUserName()
{
//This retrieves the person logged into windows/active directory
WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
//string[] fullUsername = wp.Identity.Name.Split('\\');
string fullUsername = wp.Identity.Name;
return fullUsername;
}
private static string getFirstName()
{
string firstName = getUserDataString(1);
return firstName;
}
private static string getPersonID()
{
string personID = getUserDataString(0);
return personID;
}
private static string getSecBlur()
{
string secBlur = "no_secBlur";
string mySQL = "exec get_UserAdminStatus #personID";
string cf = System.Configuration.ConfigurationManager.ConnectionStrings["DistrictAssessmentDWConnectionString"].ConnectionString;
SqlConnection connection = new SqlConnection(cf);
SqlCommand command = new SqlCommand(mySQL, connection);
command.Parameters.AddWithValue("#personID", getUserDataString(0));
connection.Open();
SqlDataReader dr = command.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
connection.Close();
if (dt.Rows.Count > 0)
{
if (dt.Rows[0]["secBlur"].ToString() == "1")
secBlur = "secBlur";
fafsa = Convert.ToInt32(dt.Rows[0]["fafsa"]);
staff = Convert.ToInt32(dt.Rows[0]["staff"]);
}
return secBlur;
}
}
If you give any class static, public values the so called "Static" (or type) Constructor will be called to do the initialization work before any access is done: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
Another common way to do initlizsation or define default values, is to use the Factory Pattern. Afaik the Graphics Class in XNA has to adapt depending if you run ona X-Box or PC, so it uses the Factory Pattern.
Of coruse with Web(anything) there is the whole issue with variable Scope, even for Statics. Much less local variables.
Below I have a method I am trying to create. The overall objective of the method is to create a list, open a database in SQL, and convert that information to a string. The problem though I am having is returning all the data. I understand for a method to work you need a return statement of some sort, however when I try to return the list, it keeps telling me
Cannot implicitly convert type 'System.Collections.Generic.List(Namespace).MyHome' to '(namespace).MyHome
So my question to you all is, can I return the list, or will I have to create another variable to return, or am I trying to return the wrong thing entirely?
Below is the method I am working on. For explanation, this method is using a class I created that holds the credentials for the data I am trying to get.
private static MyHome GetUserDataFromMyHome(string username)
{
List<MyHome> myHomeInformation = new List<MyHome>();
using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.MyHomeConnectionString))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = #"SELECT USER_NAME, EMAIL, FIRST_NAME, LAST_NAME, TRAVELER_UID FROM DATA_BASE";
connection.Open();
SqlDataReader reader = sqlError.ExecuteReader();
while (reader.Read())
{
MyHome userInformation = new MyHome();
foreach (MyHome item in myHomeInformation)
{
userInformation.myHomeUserName = Utilities.FromDBValue<string>(reader["USER_NAME"]);
userInformation.myHomeEmail = Utilities.FromDBValue<string>(reader["EMAIL"]);
userInformation.myHomeFirstName = Utilities.FromDBValue<string>(reader["FIRST_NAME"]);
userInformation.myHomeLastName = Utilities.FromDBValue<string>(reader["LAST_NAME"]);
userInformation.myHomeTravelerUID = Utilities.FromDBValue<string>(reader["TRAVELER_UID"]);
myHomeInformation.Add(userInformation);
}
}
}
return myHomeInformation;
}
Here is the class that holds the credentials:
class MyHome : IEnumerable<MyHome>
{
public string myHomeUserName { get; set; }
public string myHomeEmail { get; set; }
public string myHomeFirstName { get; set; }
public string myHomeLastName { get; set; }
public string myHomeTravelerUID { get; set; }
}
Replace
private static MyHome GetUserDataFromMyHome(string username)
with
private static List<MyHome> GetUserDataFromMyHome(string username)
the return type should be a list of objects and not just a object
A List<MyHome> is not a MyHome. If you want your function to return a List<MyHome>, declare it as such.
You have to declare the return type of the function to be a List of MyHome.
private static List<MyHome> GetUserDataFromMyHome(string username)
Otherwise whatever is calling this is expecting to get one instance of MyHome.
I'm trying to create a grid that contains all the information of a a certain ticket,that has alot of status(Rows in the table),i need to put in a grid,this is the methods i'm using:
Call the method to populate the grid:
private void AssemblyGrid()
{
//Set Grid
gridTStatus.DataSource = null;
gridTStatus.DataBind();
User loggedUser = (User)HttpContext.Current.Session[SESSIONNAME.LOGGEDUSER];
// Checa se o usuario tem permissão para utilizar essa funcionalidade
if ((loggedUser.Login.ToUpper() != ConfigurationManager.AppSettings[APPSETTINGS.SUPPORTUSERS].ToUpper()))
{
Response.Redirect("AccessDenied.aspx");
}
Clic objClic = GetClic();
Status returnStatus = new Status();
List<StatusClicComplete> lstClic = new List<StatusClicComplete>();
lstClic = ClicManager.SelectStatusClic(objClic,out returnStatus);
//Set Grid
gridTStatus.DataSource = lstClic;
gridTStatus.DataBind();
}
The method the retrieve the information from the datebase:
public List<StatusClicComplete> SelectStatusClicDB(Clic objClic , out Status returnStatus)
{
const string strStoredProcedure = "spSearchClicStatus";
List<StatusClicComplete> complete = new List<StatusClicComplete>();
try
{
Database database = DatabaseFactory.CreateDatabase(DATABASESETTINGS.CLICDB);
using (DbCommand dbCommand = database.GetStoredProcCommand(strStoredProcedure))
{
database.AddInParameter(dbCommand, "#iClic", DbType.Int32, objClic.ID);
using (IDataReader dataReader = database.ExecuteReader(dbCommand))
{
while (dataReader.Read())
{
complete.Add(new StatusClicComplete()
{
iClic = dataReader.GetInt32(Convert.ToInt32("iClic")),
iStatus = dataReader.GetInt32(Convert.ToInt32("iStatus")),
dtDateCreated = dataReader.GetDateTime(Convert.ToInt32("dtDateCreated")),
iEDV = dataReader.GetInt32(Convert.ToInt32("iEDV")),
sComments = dataReader.GetString(Convert.ToInt32("sComments"))
}
);
}
dataReader.Close();
returnStatus = StatusBuilder.BuildStatus("Success", string.Format("{0} - {1}", MethodBase.GetCurrentMethod().Name), true);
}
}
}
catch(Exception exception)
{
returnStatus = StatusBuilder.BuildStatus("Error", string.Format("{0} - {1}", MethodBase.GetCurrentMethod().Name, exception.Message), false);
}
//TODO NAV8CA - Escrever tratativa de objeto nulo
return complete;
}
The StatusClicClass ,that is the list type
namespace RB.LA.TER.CLIC.TRANSPORT
{
[Serializable]
public class StatusClicComplete
{
public int iClic { get; set; }
public int iStatus { get; set; }
public DateTime dtDateCreated { get; set; }
public int iEDV { get; set; }
public string sComments { get; set; }
}
}
And the Procedure:
PROCEDURE [dbo].[spSearchClicStatus]
#iClic int = NULL
AS
SELECT
dtDateCreated, iEDV, sComments, sDescription, SC.iStatus
FROM
T_STATUS_CLIC SC INNER JOIN T_STATUS S
ON SC.iSTATUS = S.iSTATUS
WHERE
SC.iClic = #iClic
ORDER BY
dtDateCreated
GO
I'm trying to run this code,but i'm getting a error (Input string was not in a correct format.) when it enter the complete while,someone know what i'm doing wrong?
The line dataReader.GetInt32(Convert.ToInt32("iStatus")) is wrong. It should be either
dataReader.GetInt32(4)
or
dataReader.GetInt32(dataReader.GetOrdinal("iStatus"));
In the first case, ordinal is directly specified. In the second case we calculate the ordinal using the column name. Also, you must ideally be checking for IsDBNull before using this method, otherwise you will get an InvalidCastException. So a more optimised method will be,
iClic = objClic.ID, // we already have that
iStatus = dataReader.IsDBNull(dataReader.GetOrdinal("iStatus")) ? dataReader.GetInt32(dataReader.GetOrdinal("iStatus")) : 0
P.S: Ordinal position is the position of the columns in the SELECT clause. Its a zero based index. In your select query iClic has 5th position, hence the ordinal position is given as 4.
VS2013 c# windows form.
I am learning Dapper and this is my 1st shot at it:
I have a simple class:
public class R
{
public int RID { get; set; }
public int RType { get; set; }
public string CC { get; set; }
public string RI { get; set; }
.
.
.
}
private void _setR(string rID)
{
int r_ID = Convert.ToInt16(requestID);
MY_R = new R();
SqlConnection c = new SqlConnection(Connection string);
c.Open();
var v= c.Query<R>("select RID, RType, CC, RI, .,.,., " +
"from Db_View_R where RID=#r_ID",
new { #r_ID = r_ID }) ;
c.Close();
MY_R = (R)v ; <--------- Invalid cast error here
}
The query is simple: a few columns from a view. Returns only 1 row. Not sure what am I missing here.
Thanks in advance
Extension method Query<T> returns IEnumerable<T>. So you definitely can't assign value of type IEnumerable<T> to variable of type T. You should take only one item from sequence:
MY_R = v.FirstOrDefault(); // or First, Single, SingleOrDefault
Actually with improved naming your code should look like:
var sql = "SELECT RID, RType, CC, RI FROM Db_View_R where RID = #id";
using(var conn = new SqlConnection(ConnectionString))
{
MY_R = conn.Query<R>(sql, new { id = Convert.ToInt16(requestID) })
.FirstOrDefault();
}
I still don't like names like R (it probably should be Request) but its already much more readable and safe (you should wrap connection usage in using statement).
use SingleOrDefault()
var v= c.Query<R>("select RID, RType, CC, RI, .,.,., " +
"from Db_View_R where RID=#r_ID",
new { #r_ID = r_ID }).SingleOrDefault();
I am trying to select "food_ItemName" and "food_UnitPrice" from "t_Food" table in SQL Server 2005.
I have the following code:
private void GetDatabaseConnection()
{
string connectionString = #"Server = RZS-F839AD139AA\SQLEXPRESS; Integrated Security = SSPI; Database = HotelCustomerManagementDatabase";
connection = new SqlConnection(connectionString);
connection.Open();
}
and.....
public Food PopulateFoodItemListview()
{
GetDatabaseConnection();
string selectFoodItemQuery = #"SELECT food_ItemName, food_UnitPrice FROM t_Food";
SqlCommand command = new SqlCommand(selectFoodItemQuery, connection);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
food.ItemName.Add(reader.GetString(0)); // Exception is generated in this line
food.UnitPrice.Add(reader.GetDouble(1));
}
connection.Close();
return food;
}
In food class I have the following code:
public class Food
{
private List<string> itemName;
private List<double> unitPrice;
private double itemUnit;
private Customer foodCustomer = new Customer();
public Food ()
{
}
public Food(List<string> itemName, List<double> unitPrice) : this()
{
this.itemName = itemName;
this.unitPrice = unitPrice;
}
public List<string> ItemName
{
get { return itemName; }
set { itemName = value ; }
}
public List<double> UnitPrice
{
get { return unitPrice; }
set { unitPrice = value; }
}
public double ItemUnit
{
get { return itemUnit; }
set { itemUnit = value; }
}
}
but it generating following exception. Why?
"Object reference not set to an instance of an object."
You need to create an instance of the 'itemName' and 'unitPrice' variables before you can add to either of them. You can go ahead and do that when you are declaring them.
private List<string> itemName = new List<string>();
private List<double> unitPrice = new List<string>();
Well to start:
ConnectionStrings should go into the app.config/web.config.
ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString
Use the following code to open/close connection:
using(SqlConnection connection = new SqlConnection(ConnectionString))
{
connection.Open();
}
And try to avoid having nulls in the reader...
SELECT ISNULL(food_ItemName, ''), ISNULL(food_UnitPrice, 0.0)
EDIT:
You forgot to initialize the private member of the class Food
Edit to those lines:
private List<string> itemName = new List<string>;
private List<double> unitPrice = new List<double>;
Or do it like this
public List<string> ItemName
{
get
{
if (itemName == null) itemName = new List<string>;
return itemName;
}
}
public List<double> UnitPrice
{
get
{
if (unitPrice== null) unitPrice= new List<double>;
return unitPrice;
}
}
On which variable does it complain?
It looks like the problematic one (well, maybe there are more problems but this one is for sure can cause the exception) is ItemName which is not initiated.
Have you looked at your stack trace to figure out which line the error is occurring on or which function?
From what I could see it look like it may be referring to your food object in the PopulateFoodItemListview() method. The food object is never created.