I am new to the world of c# so go easy on me! :]
I am not even sure I am using the correct terminology. I figured this would be an easy google search but I am afraid I may not be wording this correctly.
I am gathering data from a database. Like so:
SqlConnection mySqlConnection = new SqlConnection(strings.settings.connectionString);
SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
mySqlCommand.CommandText = "SELECT FNAME, LNAME, ZIPCODE FROM database WHERE ID = #ID";
mySqlCommand.Parameters.Add("#ID", SqlDbType.Char).Value = txtID.Text;
mySqlConnection.Open();
SqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader(CommandBehavior.SingleRow);
if (mySqlDataReader.HasRows == false)
{
throw new Exception();
}
if (mySqlDataReader.Read())
{
txtFname.Text = mySqlDataReader[0].ToString();
txtLname.Text = mySqlDataReader[1].ToString();
lblZipcode.Text = mySqlDataReader[2].ToString();
//need help on stringing the value ZIPCODE above.
}
My question is: How can I string the Zipcode value to another function? I have been trying things like
string Zipcode = mySqlDataReader[2].ToString();
but I get stuck trying to figure out how to string that value so I can use it in a different function like so:
private void GetZipData()
{
//Get that value
}
Any help or a point in the right direction would be greatly appreciated!
Either I've misunderstood the question or your approach is fundamentally wrong. Firstly, your GetZipData() is returning void so is a subroutine, not a function. Even better, refer to it as a method as that covers both subs and funcs...
You can pass parameters in like this...
public void GetZipData(String SomeInputString) {
///Do something
}
and you can return things from a function like this...
public String GetZipData() {
return "Some String";
}
What I suspect you want to do is get either a single Zip code or a list of zip codes from a data reader. Something like...
public String GetZipData(Integer Id) {
//All your MySQL Code here
return mySqlDataReader[2].ToString();
}
then you can simply call it like this...
String TheZipCode = GetZipData(123);
Of course, there are other things you can consider doing too - like creating a class to represent a customer and return that instead of a string - then you can get all the information in one Db trip...
class Person {
String Firstname;
String Lastname;
String ZipCode;
}
public Person GetPersonData(Integer Id) {
//All your MySQL Code here
Person ReturnData = new Person();
ReturnData.Firstname = mySqlDataReader[0].ToString();
ReturnData.Lastname = mySqlDataReader[1].ToString();
ReturnData.ZipCode = mySqlDataReader[2].ToString();
return ReturnData;
}
Then you'd have...
Person person = GetPersonData(12);
//You can now use person.Firstname, person.ZipCode, etc...
Change this method as
private string GetZipData()
{
string Zipcode = mySqlDataReader[2] as String;
return Zipcode;
}
I am not sure what you are trying to achieve. If you want to pass the zip string to antoher method, you can add a string parameter to that method
private void DoSomethingWithZipCode(string zipCode)
{
Console.WriteLine(zipCode);
}
If you want to return antoher value that depends on the zip code, you need a return type as well
private string GetCity(string zipCode)
{
string city = <get city from database>;
return city;
}
Or in your case
private string GetZipData(SqlDataReader dataReader)
{
return dataReader[2].ToString();
}
You would call it like this
lblZipcode.Text = GetZipData(mySqlDataReader);
You can also write an extension method. You must place this method in a static class whose namespace is available where you are using it
public static string ZipData(this SqlDataReader dataReader)
{
return dataReader[2].ToString();
}
You can call it like this
lblZipcode.Text = mySqlDataReader.ZipData();
string Zipcode = mySqlDataReader[2].ToString();
private void GetZipData(string yourInput)
{
//do your stuff with yourInput
}
If your top data access code is in its own method you can 'return' it from there you would then call your data access method from the new value, see below:
return ZipCode
private void GetZipData() {
var stry=DataCode();
}
Regards
Craig
Related
I am getting phone contacts into a list<> and saving it in a database.
Below is my code.
This is my method to get the contacts-List
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
try {
SetContentView(Resource.Layout.Main);
TextView txtcount = this.FindViewById<TextView>(Resource.Id.textView1);
List<PersonContact> a1 = GetPhoneContacts();
Phone gp = new Phone();
gp.insertContact(a1);
} catch (System.Exception ex) {
alert(ex.Message);
}
}
Via the following method I am trying to store contacts in database
[WebMethod]
public string insertContact<T>(List<PersonContact> a) {
OpenConnection();
if (a.Count > 0) {
for (int i = 0; i < a.Count; i++) {
string str = "insert into phone_contact (FirstName,LastName,PhoneNumber)values('" + a[i].FirstName + "','" + a[i].LastName + "','" + a[i].PhoneNumber + "')";
SqlCommand cmd = new SqlCommand(str, con);
cmd.ExecuteNonQuery();
}
return "1";
} else {
return "1";
}
}
public class PersonContact {
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
}
I am getting an error while passing parameter
gp.insertContact(a1);
Your method is generic, as it introduces a new type parameter T. That's what the <T> at the end of the method name means.
However, you don't use T anywhere - so just make it a non-generic method:
public string InsertContact(List<PersonContact> a)
At the same time, I would very strongly urge you to change the way you're doing database access: it's currently vulnerable to SQL injection attacks. Instead, you should use parameterized SQL: have one parameter for each of FirstName, LastName and PhoneNumber.
You're also returning "1" regardless of the input. Your method could be written more simply as:
// Consider renaming to InsertContacts, as it's not just dealing with a single
// contact
public string InsertContact(List<PersonContact> contacts)
{
// You should almost certainly use a using statement here, to
// dispose of the connection afterwards
OpenConnection();
foreach (var contact in contacts)
{
// Insert the contact. Use a using statement for the SqlCommand too.
}
return "1";
}
That's assuming you need the value returned at all - if you're always returning the same value, why not just make it a void method?
I am new to C# and I am creating a Form that is supposed to give the user the opportunity to enter name and age. Then, by submitting this information, there should be a summary(a new form) that shows what the user their input.
I finally got it working with the name, as it's a string and it's not a big deal, but I am stuck with the age.
I've tried casting, however, it does not work. I also looked at the documentation, but I do not find anything useful. Well, probably because I don't know where to look.
Anyway, I would strongly appreciate if someone give me an example for this.
Thanks in advance.
FormEnterDetails.cs
PersonStatic.LName = this.textBoxLastName.Text;
PersonStatic.Age = this.textBoxAge.Text;
DetailsHolder.cs
private string lName;
public string LName
{
get { return lName; }
set { lName = value; }
}
string age;
public String Age
{
get { return age; }
set { age = value; }
}
FormSummary.cs
private void FormSummary_Load(object sender, EventArgs e)
{
//we need to do this work on form load and not on creation
this.labelFirstNameSummary.Text = dh.FName;
this.labelLastNameSummary.Text = dh.LName;
this.labelAge.Text = Int32.Parse(dh.Age);
}
PersonStatic.cs
static string lName;
public static string LName
{
get { return PersonStatic.lName; }
set { PersonStatic.lName = value; }
}
static string age;
public static string Age
{
get { return PersonStatic.age;}
set { PersonStatic.age = value; }
}
I hope you want something like this
string ageString = ageInt.ToString();
Use the ToString() built-in function to convert anything to a string:
Int x=5;
String y;
y=x.ToString();
From the code you've posted, all places related to age appear to already be using string, not int (note that these are keywords that shorten the real type names, System.String and System.Int32). So you should be getting an error on this line:
this.labelAge.Text = Int32.Parse(dh.Age);
The Int32.Parse static method converts from a string to an int. (If you want to convert the other way, then as other answers have mentioned, you can call the ToString() instance method on your int.)
But in this case dh.Age, assuming dh is an instance of DetailsHolder, is already a string. And labelAge.Text, assuming labelAge is an instance of System.Windows.Forms.Label, is also a string. So you don't need to do any conversion:
this.labelAge.Text = dh.Age;
I need a Login function(login is just an example, any other frequently used method can be fine) which takes email and password as parameter and asks DB if there is such a user. If yes, it has to return customer_id(int), if no, it will return the message why login could not happen(ex:no such an email address).
I also do not wanna rewrite the login function everytime. I want to write it once in a common project which I can use in my every project and reuse it. But i am trying to find out the best practice for this. So far, i thought something like below, but the problem for me is that i cannot return customerID which i will get in codebehind in my projects(any other project) and open a session variable with it. I only can return strings in below structure. I also thought returning a Dic, but this also is wrong I guess because if bool(key) happens to be true, customerID is not a string(value). Can you help me please learning the correct way of using common functions with no need to think the returning messages and variables twice? Thanks a lot
public class UserFunctions
{
private enum Info
{
//thought of returning codes??
LoginSuccess = 401,
NoMatchPasswordEmail = 402,
InvalidEmail = 403,
};
public string TryLogin(string email, string password)
{
bool isValidEmail = Validation.ValidEmail(email);
if (isValidEmail == false)
{
return Result(Info.InvalidEmail);
// returning a message here
}
Customers customer = new Customers();
customer.email = email;
customer.password = password;
DataTable dtCustomer = customer.SelectExisting();
if (dtCustomer.Rows.Count > 0)
{
int customerID = int.Parse(dtCustomer.Rows[0]["CustomerID"].ToString());
return Result(Info.LoginSuccess);
// Here I cant return the customerID. I dont wanna open a session here because this function has no such a job. Its other projects button events job I guess
}
else
{
return Result(Info.NoMatchPasswordEmail);
}
}
private string Result(Info input)
{
switch (input)
{
case Info.NoMatchPasswordEmail:
return "Email ve şifre bilgisi uyuşmamaktadır";
case Info.InvalidEmail:
return "Geçerli bir email adresi girmelisiniz";
case Info.LoginSuccess:
return "Başarılı Login";
}
return "";
}
}
You may want to consider returning an instance of a custom class.
public class LoginResult
{
public Info Result { get; set; }
public int CustomerId { get; set;}
}
Modify your TryLogin method to return an instance of LoginResult.
Base your application flow on the result:
var loginResult = TryLogin(..., ...);
switch (loginResult.Result)
{
case Info.LoginSuccess:
var customerId = loginResult.CustomerId;
//do your duty
break;
case Info.NoMatchPasswordEmail:
//Yell at them
break;
...
}
You could try Creating an event and then the calling code can register to the event before attempting to login.
For example:
public class UserFunctions
{
private enum Info
{
LoginSuccess = 401,
NoMatchPasswordEmail = 402,
InvalidEmail = 403,
};
public delegate void LoginAttemptArgs(object sender, Info result, int CustomerID);//Define the delegate paramters to pass to the objects registered to the event.
public event LoginAttemptArgs LoginAttempt;//The event name and what delegate to use.
public void TryLogin(string email, string password)
{
bool isValidEmail = Validation.ValidEmail(email);
if (isValidEmail == false)
{
OnLoginAttempt(Info.InvalidEmail, -1);
}
Customers customer = new Customers();
customer.email = email;
customer.password = password;
DataTable dtCustomer = customer.SelectExisting();
if (dtCustomer.Rows.Count > 0)
{
int customerID = int.Parse(dtCustomer.Rows[0]["CustomerID"].ToString());
OnLoginAttempt(Info.LoginSuccess, customerID);
}
else
{
OnLoginAttempt(Info.NoMatchPasswordEmail, -1);
}
}
private void OnLoginAttempt(Info info, int CustomerID)
{
if (LoginAttempt != null)//If something has registered to this event
LoginAttempt(this, info, CustomerID);
}
}
I wouldn't compile a string to return, I would return the enum result and let the calling code do what it likes with the result. reading an enum is much quicker than parsing returned string.
Edit: Typos and i missed an event call... .Twice
hello guys i have a form... and i set my properties if the user will click the submit button and after then i will call my add_data function which contains my database query...but the problem is the properties I've set in my form will become empty in my add_data function...why this is happening?
actually i already try adding a messagebox in my form which contains the data in my properties after setting my properties value and it works fine but when i add it to my databasecon class the messagebox shows null... i try also putting my properties and database query function in the same class and it's working but what i want is to separate my properties and my database query functions...
this is the codes in my properties
class persons
{
//person attributes
private string fname;
private string lname;
private string age;
private string gnder;
private string address;
//initialize
public persons()
{
this.fname = "";
this.lname = "";
this.age = "";
this.gnder = "";
this.address = "";
}
//set and get properties
public string p_fname
{
get { return this.fname; }
set { this.fname = value; }
}
public string p_lname
{
get { return this.lname; }
set { this.lname = value; }
}
public string p_age
{
get { return this.age; }
set { this.age = value; }
}
public string p_gender
{
get { return this.gnder; }
set { this.gnder = value; }
}
public string p_address
{
get { return this.address; }
set { this.address = value; }
}
}
this is the codes in my form
public partial class add : Form
{
persons p = new persons();
databasecon d = new databasecon();
private void addbtn_Click(object sender, EventArgs e)
{
p.p_fname = this.fname.Text;
p.p_lname = this.lname.Text;
p.p_age = this.age.Text;
p.p_gender = this.gender.Text;
p.p_address = this.address.Text;
d.add_data();
this.Close();
}
}
and this is the codes in my database connection and queries
class databasecon
{
OleDbConnection con = new OleDbConnection();
persons p = new persons();
public databasecon()
{
con.ConnectionString = "Provider=Microsoft.JET.OLEDB.4.0;Data Source=../dbsample.mdb";
}
public void add_data()
{
try
{
con.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO person(u_fname,u_lname,u_age,u_gender,u_address)VALUES('" + p.p_fname + "','" + p.p_lname + "','" + p.p_age + "','" + p.p_gender + "','" + p.p_address + "')";
cmd.Parameters.AddWithValue("u_fname", p.p_fname);
cmd.Parameters.AddWithValue("u_lname", p.p_lname);
cmd.Parameters.AddWithValue("u_age", p.p_age);
cmd.Parameters.AddWithValue("u_gender", p.p_gender);
cmd.Parameters.AddWithValue("u_address", p.p_address);
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
MessageBox.Show("Error : " + e);
}
finally
{
con.Close();
MessageBox.Show("New person has been successfully added.");
}
}
}
You need to pass p as a parameter to the add_data method.
public void add_data(persons person)
then call it with the parameter:
d.add_data(p);
and use the properties of person in the method:
cmd.Parameters.AddWithValue("u_fname", person.p_fname);
cmd.Parameters.AddWithValue("u_lname", person.p_lname);
cmd.Parameters.AddWithValue("u_age", person.p_age);
cmd.Parameters.AddWithValue("u_gender", person.p_gender);
cmd.Parameters.AddWithValue("u_address", person.p_address);
you create databasecon() in form and then call add_data method and you don't pass 'persons' instance. in databasecon you use persons istnace which is field in this class. you soudl add parameter do add_data method and pass instance or 'persons' you want to save and use it in command
Your p fields in your add and databasecon classes are separate. When you call d.add_data(), the d object can only see its instance of persons p ....
To fix this, pass the persons object into the add_data method.
class databasecon{
// Remove this line, we pass it into the function below
/* persons p = new persons(); */
public void add_data(persons p){
try{
// same code as before
}catch(Exception e){
// same code
}
finally{
// same
}
}
}
You have an instance of Person class which you fill and then use an instance of databasecon which is completely not conntected to the person class you filled.
Change add_data() to
public void add_data(person p) { ... }
this will use the properties from p passed as parameter.
You call it like this
d.add_data(p);
Except for that have a look at some C# for begginers book.
Overlooking the fact that your code is extremely poorly written.
You are not passing in the persons class that you created.
Something like
public void add_data(persons p) {//..blah}
Then
private void addbtn_Click(object sender, EventArgs e) {
p.p_fname = this.fname.Text;
p.p_lname = this.lname.Text;
p.p_age = this.age.Text;
p.p_gender = this.gender.Text;
p.p_address = this.address.Text;
d.add_data(p);
this.Close();
}
From what I can see in the code above, you call add_data from your databasecon class, which has an instance p of Person. Since you are not passing a Person object to your add_data method, the empty, unset p object is what is being saved to the database.
Adding a Person parameter to add_data and use that when saving the data to the database.
There are several things I don't like in your code.
Let's start however with your specific problem:
Your code contains also a source of security issues and malignous SQL code injection.
You are saving always an empty person and there is a problem with your SQL connection string.
Try this code instead.
private void addbtn_Click(object sender, EventArgs e)
{
try
{
persons p = new persons(); // we use a new instance of person class
p.p_fname = this.fname.Text;
p.p_lname = this.lname.Text;
p.p_age = this.age.Text;
p.p_gender = this.gender.Text;
p.p_address = this.address.Text;
d.add_data(p); // we save the instance of persons
this.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error : " + e);
}
}
...
class databasecon
{
public void add_data(person p) // we need a person as parameter
{
OleDbConnection con = new OleDbConnection();
con.ConnectionString = "Provider=Microsoft.JET.OLEDB.4.0;Data Source=../dbsample.mdb";
con.Open();
try
{
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
// this is the correct sql command string
cmd.CommandText = "INSERT INTO person(u_fname,u_lname,u_age,u_gender,u_address) " +
VALUES (#u_fname, #u_lname, #u_age, #u_gender, #u_address)";
cmd.Parameters.AddWithValue("u_fname", p.p_fname);
cmd.Parameters.AddWithValue("u_lname", p.p_lname);
cmd.Parameters.AddWithValue("u_age", p.p_age);
cmd.Parameters.AddWithValue("u_gender", p.p_gender);
cmd.Parameters.AddWithValue("u_address", p.p_address);
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
...
}
Now let's talk about code style.
Is a good thing to use CamelCase style in your code, look on the web about C# CamelCase:
Classes and properties should all start with a capitalized letter.
Your class express a single person not a list of persons so its name should be public class Person.
Avoid the use achronims or of short names when you can...
p_lname should be LastName, people will thanks you if you make your code more readable, C# is not C and C# is not PHP!
A field or a property with a longer name will not consume more memory than a property with a short and unreadable name :)
Use always strong typing... age is not a string, age is an integer.
The property should be public int Age, not a string!
Never use MessageBox in your non-visual classes.
Try to catch for exceptions in your client code, not in your library code!
I dont know if I 100% understand the issue about I guess it's because your inserting an empty persons class into the db.
Your `add_data method should take a person object like so.
public void add_data(persons obj)
{
p = obj;
you must pass person object to add_data method
public void add_data(persons p)
{
...
}
and call it:
d.add_data(p);
Update:
I have a dropdownlist with seven different options like (date, subject, press, cia, media...) and user will select one of the item from the dropdownlist and click on search button to get the results.
Here is my repository class GetInquiries method which accepts 7 parameters but it will pass only one parameters at a time to the stored procedure and in case of Date (it will pass both from/to)
public List<Inquiry> GetInquiries(string fromDate, string toDate,
string subject, string press,
string cia, string media,
string status)
Here is what I have come up with passing the parameters to GetInquiries:
if (!string.IsNullOrEmpty(this.txtSubject.Text.Trim()))
{
e.Result = reporterRepo.GetInquiries(null,null,txtSubject.Text,null,null,null,null);
}
else
{
e.Result = reporterRepo.GetInquiries(null,null,null,null,null,null,null);
}
else if (!string.IsNullOrEmpty(this.fromDate.Text.Trim()))
e.Result = reporterRepo.GetInquiries(fromDate.Text,null,null,null,null,null,null)
.......................
...................
....................
I have to continue seven times with (if else if conditions) for all seven parameters.
Is there a way I can do it more clearly and more readability?
Well, depending on your exact situation, this might help:
e.Result = reporterRepo.GetInquiries(null, null,
string.IsNullOrEmpty(this.txtSubject.Text.Trim()) ? null : txtSubject.Text,
null, null, null, null);
Or if you're using C# 4 and can modify GetInquiries, you could possibly make all the parameters optional and use named arguments to specify which one you're actually providing.
Or write methods such as GetInquiriesByName, GetInquiriesBySubject etc to avoid overloading with clashing parameter types.
EDIT: If there's a dropdown, it sounds like you should be using the value of that to determine the appropriate branch to take (i.e. what to search on) and then go from there.
If you are using .NET 4.0 then you take advantge of optional and default parameters. If you're using an earlier framework version, then try creating overloasd of the routine:
public List<Inquiry> GetInquiries(string fromDate, string toDate,
string subject, string press,
string cia, string media)
{
// Pass empty string for status.
return this.GetInquiries(fromDate, toDate, subject, press, cia, media, String.Empty)
}
public List<Inquiry> GetInquiries(string fromDate, string toDate,
string subject, string press,
string cia, string media,
string status)
var subjectText = this.txtSubject.Text.Trim();
var dateText = this.fromDate.Text.Trim();
if (subjectText.Length == 0) subjectText = null;
if (dateText .Length == 0) dateText = null;
e.Result = reporterRepo.GetInquiries(dateText ,null,subjectText,
null,null,null,null);
string.IsNullOrEmpty(this.txtSubject.Text.Trim()))
Note that this.txtSubject.Text.Trim() will never be null, and if this.txtSubject.Text is null, this will throw an exception.
You reflection to invoke the method GetInquiries with just the n-th argument set.
public List<Inquiry> GetInquiries(int numparam, string myparameter)
{
object[] params = new object[7];
params[numparam] = myparameter;
reporterRepo.Gettype().GetMethod("GetInquiries").Invoke(reporterRepo, params);
}
I have not tested the code but you get the idea.
public class Inquiries
{
private SqlParameter[] _parameters;
public DateTime FromDate { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public DateTime ToDate { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public String Subject { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public String Press { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public String Cia { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public String Media { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public List<Inquiry> Get()
{
// Your dal code using the parameters array
}
}
Then make Inquiries a member level in the formthat's going to get inquiries, and with the changes you do, set the properties appropriately, unless you're only going to do one property at a time then just create the class and toss it each time you use it as:
List<Inquiry> myInquires = new Inquiry() { Subject = txtSubject.Text }.Get();
What about using some sort of a specification pattern
So in your example the usage would be
var querySpecification = new QuerySpecification();
if (!string.IsNullOrEmpty(this.txtSubject.Text.Trim()))
{
querySpecification = new WhereSubject().Is(txtSubject);
}
else if (!string.IsNullOrEmpty(this.fromDate.Text.Trim()))
{
querySpecification = new WhereFromDate().Is(fromDate);
}
else
{
querySpecification = new All();
}
e.Result = reporterRepo.GetInquiries(querySpecification);
WhereSubject, WhereFromDate and All derives from a common IReportReposSpec.
public interface IReportReposSpec
{
void Is(object value)
// stored proc translation of the spec
string Param {get;}
string DbType {get;}
string Value {get;}
}
The implementation of reporterRepo.GetInquiries could be as such
public List<Inquiry> GetInquiries(IReportReposSpec spec)
{
var cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
// for simplicity i'm going to use a pseudo code from here on
cmd.AddParam(spec.Param, spec.DbType, spec.Value));
//...
}