Check if user ID exist in SQL database - c#

I'm a beginner programmer and I'm writing a C# application that makes a query to a database. However I am wondering how could I check that an ID exists (ID is entered by user in the console application) and if it doesn't, display a message.
Here's my code:
Console.WriteLine("enter ID");
try
{
var province_id = Convert.ToInt32(Console.ReadLine());
var aquery2 = from test in context.BusinessEntityAddress
where test.Address.StateProvinceID == province_id
group test.BusinessEntity.Person.LastName by new { test.BusinessEntityID, test.BusinessEntity.Person.LastName, test.BusinessEntity.Person.FirstName }
into balk
select new {
...
};
Didn't paste the whole code but this is the part my question is about. At the line
where test.Address.StateProvinceID == userid
I would like to check if that ID exist in the database, and if it doesn't, display a message. I don't know how to do that.
Note that all the code is already in a try{}catch{} because I also need to ensure that the user input is an integer.
Thank you

It seems like you're trying to do a lot more then just search for a user ID in your question? You seem to be saying StateProvinceId is a user Id? In which case a simple test like this should suffice:
if (!context.Addresses.Any(a => a.StateProvinceID == userid))
{
Console.WriteLine("User doesn't exist");
}
Although, it would seem more logical to look in a users table. EG, context.Users. Which would hence question why you are doing a group by (which shouldn't be needed).
You will need to add each data object to your context, but if you could elaborate more on what exactly isn't working, we can help more.

You don't need to run the code inside a try for that, instead first you have to check for the existence of the user:
int number;
//check if the userId is an integer
if(!int.TryParse(userId, out number)){
Console.WriteLine("Please enter a valid interger!!");
return;
}
var beAddress = context.BusinessEntityAddress;
//check for the userId exist in the DB
var flag = beAddress.Any(a => a.Address.StateProvinceID == number);
if(flag){
//do something if the user exist
}
else{
//do something else if the user doesn't exist
}
For checking if the string is a valid integer you should use int.TryParse("8", NumberStyles.Integer, System.Globalization.NumberFormatInfo.InvariantInfo, out number);, this way you are not just checking if the string is a number but if is an integer.

You shouldn't use try-catch for a classic user error, like number parsing. int.TryParse() is made for this :
// get rid of the try-catch, you wont need it anymore
int userid;
var input = Console.ReadLine();
if (!int.TryParse(input, out userID))
{
Console.WriteLine("Invalid input : '{0}' is not a number", input);
return;
}
var aquery2 = from test in context.BusinessEntityAddress
where test.Address.StateProvinceID == userid
group test.BusinessEntity.Person.LastName by new { test.BusinessEntityID, test.BusinessEntity.Person.LastName, test.BusinessEntity.Person.FirstName } into balk
select new
{
/* ... */
};
if (!aquery2.Any())
{
// not found... display a message
}
else
{
// found... do stuffs
}

This is the code which I'm using. I don't know about console application but know little bit about C# and SQL. I'm not sure I understood clearly but just hope this might help you. Thank you.
bool idfound; (declare in the field of a Class)
private void buttonIDcheck_Click(object sender, RoutedEventArgs e)
(a Event which has to be created by Visual Studio, not manually)
{
SqlConnection Conn = new SqlConnection();
Conn.ConnectionString = yourConnectionString;
Conn.Open();
SqlCommand check_idexistcomm = new SqlCommand();
check_idexistcomm.Connection = Conn;
check_idexistcomm.CommandText = "SELECT id FROM yourtable";
var check_idexistda = new SqlDataAdapter(check_idexistcomm);
SqlDataReader check_idexistreader = check_idexistcomm.ExecuteReader();
while (check_idexistreader.Read())
{
if (check_idexistreader["id"].ToString()== text value inputed by user here)
{
idfound = true;
break;
}
}
check_idexistreader.Close();
Conn.Close();
if (idfound=true)
{
your code here to accept the user as authorized
}
else
{
MessageBox.Show("Sorry, you're not authorized");
}
}

Related

Update sql database without blanks fields

I am trying to figure out a way for my program not to update the sql database if some fields are blank when I hit the submit form. Right now when I submit it to the sql database, if the fields are blank, it updates it as blank. Is there a way for my code not to behave like this?
Thanks
//field names in the table
string update = #"UPDATE Master_List
SET Date_Complete1 = #Date_Complete1, Pass_Fail = #Pass_Fail, CRC_Number = #CRC_Number, QN_Number = #QN_Number, Notes = #Notes WHERE Job_Number = #Job_Number"; //parameter names
using (SqlConnection conn = new SqlConnection(connString)) //using allows disposing of low level resources
{
try
{
conn.Open();//open new connection
command = new SqlCommand(update, conn); // create the new sql command object
// Read value from form and save to the table
command.Parameters.AddWithValue(#"Job_Number", jobTxt.Text);
command.Parameters.AddWithValue(#"Pass_Fail", comboBox1.Text);
command.Parameters.AddWithValue(#"Date_Complete1", opBox1.Text);
command.Parameters.AddWithValue(#"CRC_Number", crcTxt.Text);
command.Parameters.AddWithValue(#"QN_Number", qnTxt.Text);
command.Parameters.AddWithValue(#"Notes", notesTxt.Text);
command.ExecuteNonQuery(); // Push form into the table
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); // If there is something wrong, show the user message
}
}
Assuming that you want to update some of the fields if one or more fields are blank, then you can do this:
UPDATE Master_List
SET Date_Complete1 = ISNULL(NULLIF(#Date_Complete1,''),Date_Complete1),
Pass_Fail = ISNULL(NULLIF(#Pass_Fail,''),Pass_Fail),
CRC_Number = ISNULL(NULLIF(#CRC_Number,''),CRC_Number),
QN_Number = ISNULL(NULLIF(#QN_Number,''),QN_Number),
Notes = ISNULL(NULLIF(#Notes,''),Notes)
WHERE Job_Number = #Job_Number
If you don't want any fields to update if any fields are blank, then just check them in an if statement.
Perform checks on your input data before your sql code is executed.
simply return out of the function if any checks you want to do fail e.g.
If(string.IsNullOrEmpty(variable to check))
... Return or configure error message for user ...
Or perform some logic to show the user you dont want blank fields.
If you are going to validate that you should change your database field properties to do that task.
if you want to do this with some code you should add something like this:
bool val = true;
if (jobTxt.Text.Trim() == string.Empty) {
val = false;
}
if(val==true){
command.ExecuteNonQuery();
}
else{
MessageBox.Show("Some field is empty")
}
and repite the sentence if for each textbox you want to do a validation.
i hope this help you.
You can say which textbox is empty on the else sentences on the textbox.

Parse.com - if key exists, update

Currently, I'm sending some data to Parse.com. All works well, however, I would like to add a row if it's a new user or update the current table if it's an old user.
So what I need to do is check if the current Facebook ID (the key I'm using) shows up anywhere in the fbid column, then update it if case may be.
How can I check if the key exists in the column?
Also, I'm using C#/Unity.
static void sendToParse()
{
ParseObject currentUser = new ParseObject("Game");
currentUser["name"] = fbname;
currentUser["email"] = fbemail;
currentUser["fbid"] = FB.UserId;
Task saveTask = currentUser.SaveAsync();
Debug.LogError("Sent to Parse");
}
Okay, I figured it out.
First, I check which if there is any Facebook ID in the table that matches the current ID, then get the number of matches.
public static void getObjectID()
{
var query = ParseObject.GetQuery("IdealStunts")
.WhereEqualTo("fbid", FB.UserId);
query.FirstAsync().ContinueWith(t =>
{
ParseObject obj = t.Result;
objectID = obj.ObjectId;
Debug.LogError(objectID);
});
}
If there is any key matching the current Facebook ID, don't do anything. If there aren't, just add a new user.
public static void sendToParse()
{
if (count != 0)
{
Debug.LogError("Already exists");
}
else
{
ParseObject currentUser = new ParseObject("IdealStunts");
currentUser["name"] = fbname;
currentUser["email"] = fbemail;
currentUser["fbid"] = FB.UserId;
Task saveTask = currentUser.SaveAsync();
Debug.LogError("New User");
}
}
You will have to do a StartCoroutine for sendToParse, so getObjectID has time to look through the table.
It may be a crappy implementation, but it works.
What you need to do is create a query for the fbid. If the query returns an object, you update it. If not, you create a new.
I'm not proficient with C#, but here is an example in Objective-C:
PFQuery *query = [PFQuery queryWithClassName:#"Yourclass]; // Name of your class in Parse
query.cachePolicy = kPFCachePolicyNetworkOnly;
[query whereKey:#"fbid" equalTo:theFBid]; // Variable containing the fb id
NSArray *users = [query findObjects];
self.currentFacebookUser = [users lastObject]; // Array should contain only 1 object
if (self.currentFacebookUser) { // Might have to test for NULL, but probably not
// Update the object and save it
} else {
// Create a new object
}

Solving Redirect Loop

I know what is causing the Redirect loop in my code, I am just not sure how to fix it. First, my code.
switch (Request.QueryString["Error_ID"])
{
case "1":
// Error Code 1 is when a user attempts to access the Admin section and does not have rights to.
MultiView1.ActiveViewIndex = 1;
break;
case "2":
// Error Code 2 is when a user is not currently Active.
MultiView1.ActiveViewIndex = 2;
break;
default:
// Default is View Index 0 for default access.
MultiView1.ActiveViewIndex = 0;
break;
}
// Get current username.
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
// Test to see if user is Active.
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["HSEProjRegConnectionString1"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT [active] FROM [tbl_Person] WHERE username LIKE #username", conn))
{
cmd.Parameters.AddWithValue("#username", "%" + userName + "%");
var res = cmd.ExecuteScalar();
bool registeredAndActive = (bool)res;
if (registeredAndActive)
{
// Active Condition. The DEFAULT in SWITCH() will take care of displaying content.
}
else
{
// !Active Condition. Shows an alternative version of the default page where the user is told they do not have access.
Response.Redirect("default.aspx?Error_ID=2");
}
}
The point of the code is to first check for a Query String in the SWITCH() method in case one is provided on a later page. Then it grabs current AD username logged in with, and then checks a user database to see if the user is marked Active. If so, it does nothing as it will allow the page to load as normal. If not, then it redirects to the same page but appends an Error_ID so that I can display a different View saying that the user does not have access. I am pretty sure this is where the redirect loop is coming from. Does anyone have any ideas on how I can eliminate Redirect Loop? I tried doing a Request.Url.ToString() and then a !var.Contains to do the Redirect, but I couldn't make that work either.
EDIT: I should note that I am interested to hear if anyone has any alternatives to Response.Redirect(). It works, but originally, I was using Response.End() and that didn't allow any code to run so came up with using Response.Redirect() and a QueryString to do what I wanted.
You are testing if your user is active twice. Also, in the second check, you keep redirecting the page to itself, which keeps doing the checks.
Your first check is here:
switch (Request.QueryString["Error_ID"])
{
(...)
case "2":
// Error Code 2 is when a user is not currently Active.
MultiView1.ActiveViewIndex = 2;
break;
(...)
and your second check is here:
if (registeredAndActive)
{
// Active Condition. The DEFAULT in SWITCH() will take care of displaying content.
}
else
{
// !Active Condition. Shows an alternative version of the default page where the user is told they do not have acces.
Response.Redirect("default.aspx?Error_ID=2");
}
So the second check redirects the page to itself, and it keeps looping forever.
The easiest way to fix this, IMHO, is to not check if your current user is active if your error code is "2", i.e. you could either:
1) Stop the page execution if Error_ID is 2, i.e. change the first check to:
case "2":
// Error Code 2 is when a user is not currently Active.
MultiView1.ActiveViewIndex = 2;
Response.End(); // <--- this will stop the execution before reaching the first block
break;
2) Don't redirect the page again, if Error_ID is 2, i.e. change your second check to:
if (registeredAndActive)
{
// Active Condition. The DEFAULT in SWITCH() will take care of displaying content.
}
else
{
// !Active Condition. Shows an alternative version of the default page where the user is told they do not have acces.
if (MultiView1.ActiveViewIndex != 2) { // check if the page has already been redirected
Response.Redirect("default.aspx?Error_ID=2");
}
}
IMHO, solution 2 seems to be the cleanest and most elegant of the two
You only need to perform the database check if the query string value (Error_ID) is not 1 or 2. The way the logic is written, you will always check for whether or not the user is active and if they are not, then it will keep sending the Error_ID=2 query string value to the page and you will be stuck in a loop. I would recommend separating out the logic to test for the query string into a separate method and have it return a Boolean of whether or not to attempt to query the database for the Active value.
How about doing something like this:
if(MultiView1.ActiveViewIndex != 2)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["HSEProjRegConnectionString1"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT [active] FROM [tbl_Person] WHERE username LIKE #username", conn))
{
cmd.Parameters.AddWithValue("#username", "%" + userName + "%");
var res = cmd.ExecuteScalar();
bool registeredAndActive = (bool)res;
if (registeredAndActive)
{
// Active Condition. The DEFAULT in SWITCH() will take care of displaying content.
}
else
{
// !Active Condition. Shows an alternative version of the default page where the user is told they do not have acces.
Response.Redirect("default.aspx?Error_ID=2");
}
}
}
}

Unit testing functions which access Entity Database

Trying to unit test functions which access a entity framework. So i tried to put all the entity code into the test function below? However it stops at the Linq statement; obviously trying to access the database is too much drama for it. Maybe a work around would be too to create a replica database within the unit test function based on sql lite or compact;(Its not a big database anyways) then execution would not have to leave the test function? Is this possible and how would i implement it?
public void RetreiveKeyFnTest()
{
StegApp target = new StegApp(); // TODO: Initialize to an appropriate value
string username = "david"; // TODO: Initialize to an appropriate value
string password = "david1"; // TODO: Initialize to an appropriate value
string ConnectionString = ConfigurationManager.ConnectionStrings["DatabaseEntities"].ToString();
var dataContext = new DatabaseEntities(ConnectionString);
var user = dataContext.Users.FirstOrDefault(u => u.Username.Equals(username) && u.Password.Equals(password));
Assert.IsNotNull(user);
//target.RetreiveKeyFn(username, password);
//Assert.IsInstanceOfType(target.RetreiveLogs,typeof(DataAccess));
//Assert.IsInstanceOfType(target.p);
//Assert.IsNotNull(target.RetreiveLogs.AuthenitcateCredentials(username,password));
//Assert.Inconclusive("A method that does not return a value cannot be verified.");
}
Below is the code i am trying to test:
public void RetreiveKeyFn(string username, string password)
{
BusinessObjects.User p = RetreiveLogs.AuthenitcateCredentials(username,password);
if (p != null)
{
if (RetreiveLogs.RetreiveMessages(p.UserId) == null)
{
DisplayLogs.Text = "Sorry No messages for you recorded in Database, your correspondant might have chose not to record the entry";
}
else
{
MessageBox.Show("LogId = " + RetreiveLogs.RetreiveMessages(p.UserId).LogId + "\n" +
"UserId = " + RetreiveLogs.RetreiveMessages(p.UserId).UserId + "\n" +
"Message Key = " + RetreiveLogs.RetreiveMessages(p.UserId).MessageKey + "\n" + "PictureId = " + RetreiveLogs.RetreiveMessages(p.UserId).PictureId +
" Date & time = " + RetreiveLogs.RetreiveMessages(p.UserId).SentDateTime);
DisplayLogs.Visible = true;
}
}
else
{
MessageBox.Show("Please enter your correct username and password in order to retreive either key, image or both from Databse");
}
}
First, you should be able to access the same database in your test application as the one you're using in your main/actual application. You just need to make sure that your Test project contains your connection string in its own App.config.
The initialization of the context should be done either inside your StegApp(), or you should be able to pass a context to your StegApp() from a different scope. From what I read of your code, your StegApp() will not be able to access the dataContext variable you created.
Your test for null user already happens inside the RetrieveKeyFn() under the AuthenticateCredentials() method so there's no need for the first "Assert.IsNotNull(user)". I would recommend separating your business logic for RetrieveKeyFn from your UI behaviors so that you can easily do unit tests. You can bind the "Messagebox" operations to say a button click event handler which calls just RetrieveKeyFn(). I would suggest maybe something like this:
public class StegApp
{
public DatabaseEntities context;
//other properties
public StegApp()
{
//assuming your DatabaseEntities class inherits from DbContext.
//You should create other constructors that allow you to set options
//like lazy loading and mappings
this.context = new DatabaseEntities();
}
//ASSUMING YOUR RetrieveLogs.RetrieveMessages() function returns
//a Message object. replace this type with whatever type the
//RetrieveLogs.RetrieveMessages() method returns.
public Message RetrieveKeyFn (string username, string password)
{
BusinessObjects.User p = RetreiveLogs.AuthenitcateCredentials(username,password);
if (p != null)
{
var message = RetrieveLogs.RetrieveMessages(p.UserId);
if (message == null)
// handle behavior for no messages. In this case
// I will just create a new Message object with a -1 LogId
return new Message {LogId =-1};
else
return message;
}
else
//handle behavior when the user is not authenticated.
//In this case I throw an exception
throw new Exception();
}
//on your button click handler, do something like:
// try
// {
// var message = RetrieveKeyFn(txtUsername.Text.Trim(), txtPassword.Text.Trim());
// if (message.LogId == -1)
// DisplayLogs.Text = "Sorry No messages for you recorded in Database, your correspondant might have chose not to record the entry";
// else
// {
// MessageBox.Show("Log Id = " + message.LogId)
// etc. etc. etc.
// }
// }
// catch
// {
// MessageBox.Show ("user is not authenticated");
// }
}
When you do your unit test, remember to have the appropriate configuration strings in your test project's App.Config If the app.config does not yet exist, go ahead and create one. You should create tests for all possibilities (i.e. 1) user is valid, you get the message, 2) user is valid, there are no messages, 3) user is invalid).
Here's an example for case 2
[TestMethod]
public void RetrieveKeyFnTest1()
{
StegApp target = new StegApp(); // this creates your context. I'm assuming it also creates your RetrieveLogs object, etc
var username = "UserWithNotMessages"; //this user should exist in your database but should not have any messages. You could insert this user as part of your TestInitialize method
var password = "UserWithNotMessagesPassword"; //this should be the proper password
var message = target.RetrieveKeyFn(username, password);
Assert.AreEqual (-1, message.LogId);
}
I got my unit tests to work fine. The mistake i had was not to copy the app.config file into the test project! Although to be honest i expected Visual studio would have done that anyways.

C# visual if/else issue

Hi having abit of a problem with my code it refuses to do my else statement have a global variable set to say attempts = 3
runs the while loop but when i put an invalid pin it basically just doesnt run anything i would appreciate any help possible thanks
while (read.Read())
{
if (read.HasRows)
{
}
//If the card isnt confiscated then do this:
if (((Boolean)(read["confiscated"]) == false))
{
string cardnum = read["cardNumber"].ToString();
string pinnum = read["PIN"].ToString();
//Compare the results in the table against those put in by the customer
if (string.Equals(cardnum, cardBox.Text) && string.Equals(pinnum, pinNumber.Text))
{
MessageBox.Show("Welcome customer");
MessageBox.Show("Card Number " + cardnum + " PIN " + pinnum);
//if the login details match and everything is correct then bring the next form up
MessageBox.Show("Details are correct");
pinNumber.Clear();
//open the options form
Form optionForm = new optionForm();
optionForm.Show();
//hide this form
this.Hide();
break;
}
else
{
if (attempts == 1)
{
sqlCommandATM.Parameters["#cardNum"].Value = cardBox.Text;
sqlCommandATM.Parameters["#confiscated"].Value = true;
MessageBox.Show("Your card has been confiscated please contact The bank of Glamorgan to resolve the issue");
pinNumber.Clear();
}
EDIT
I've tried to understand what you're doing. I assume you're trying to authenticate a person by credit card number and PIN against a database, and you're doing it by getting all the entries from a database table and looping over them to find the one that matches the user input. You want to allow the user to do that three times before locking the credit card.
I see more than one issue with that: The task of finding the correct row in the table for the user should be left to the database. This is much quicker and less error prone. So if you'd like to do it right, then you should have an SQL statement like:
int attempts = 0;
bool success = false;
while (!success && attempts < 3)
{
using (SQLCommand exists = new SQLCommand("SELECT ID FROM ... WHERE CCardNo = #cardNo AND PIN = #pin", conn))
{
exists.Parameters.AddWithValue("#cardNo", cardNum);
exists.Parameters.AddWithValue("#PIN", pinnum);
object idObject = (int)exists.ExecuteScalar();
if (idObject == null || idObject == DBNull.Value)
{
attemps++;
}
else
{
success = true;
}
if (attempts >= 3)
{
// Lock out the user
}
}
}
if (success)
{
...
}
If you really insist on doing it your way, then please make sure that attempts is initialized properly and is incremented on each login attempt - in your current code, you'd increment it on every row you're validating against, so you'd lock out every customer who's not within the first three rows you're getting from the database.
Original reply
OK, you're reading all data from a DataReader in a while loop:
while (read.Read())
{
Then what do the following three lines do? You wouldn't be here if read.HasRows was false, because read.Read() would have returned false already. The following three lines are pointless and can be removed, leaving only what's inside the block.
if (read.HasRows)
{
}
The usual way would be:
if (read.HasRows)
{
while (read.Read())
{
...
}
}
More is hard to tell as you're not showing us the complete code - what value does attempts have before the while loop, for example?
Ignoring the syntax errors in your posted code, my first guess is that your attempts variable is not set to 1 when control goes inside the else statement so, based on your posted code, nothing should happen. Could you show us where this attempts variable is declared/changed?
From the code supplied you have not incremented attempts on each attempt the user trys to enter a pin. where teh code is;
string pinnum = read["PIN"].ToString();
attempts++;
Something like that. Its hard to tell what you have in total as its obviously snipped code.
You said the global attempts = 3.
If that's the case, you should check if the failed attempts is >= 3.
if (string.Equals(cardnum, cardBox.Text) && string.Equals(pinnum, pinNumber.Text))
{
// Load account
}
else if (attempts >= 3)
{
// Confiscate card
}
else
{
attempts ++;
}

Categories

Resources