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 have a databsase called Patients with Table Conditions that has the following fields:
ConditionID(PK) int(50) AI,
ID_No(PK)(FK) bigint,
Date date,
Diagnosis varchar(50),
Notes varchar(max)
I have a C# windows form application called Records which should read the data in the Table Conditions and show it under the tab Condition in tabcontrol1 in the Records Form.
I have another class called Misc.cs that has the connection string (as my project has many forms and I avoided having the code for connecting duplicated on every form)
Below is code from Misc.cs that connects and reads data from the database:
class Misc
{
SqlConnection con = new SqlConnection(#"DataSource=.\SQLEXPRESS;AttachDbFilename=G:\BiometricSystem\BiometricSystem\Patients.mdf;Integrated Security=True;User Instance=True");
SqlCommand cmd = new SqlCommand();
SqlDataAdapter a = new SqlDataAdapter();
SqlDataReader dr;
public static long Id;
public void connect()
{
cmd.Connection = con;
}
public void getConditions()
{
connect();
con.Open();
cmd.CommandText = "SELECT * FROM Condition WHERE ID_No = '" + Id + "'";
dr = cmd.ExecuteReader();
Records r = new Records();
if (dr.HasRows)
{
while (dr.Read())
{
r.setdiagnosis(dr[0].ToString());
r.setDate(dr[1].ToString());
r.setNotes(dr[2].ToString());
r.printConditions();
}
}
else
System.Windows.Forms.MessageBox.Show("No records to display");
closeConn();
}
}
This code is invoked in Records.cs as follows:
public partial class Records : Form
{
Misc misc = new Misc();
long patID = Misc.Id;
private string diagnosis, datum ,dinota;
public Records()
{
InitializeComponent();
diagnosis = "";
datum = "";
dinota = "";
}
public void setdiagnosis(string dx)
{
diagnosis = dx;
}
public string getdiagnosis()
{
return diagnosis;
}
public void setDate(string date)
{
datum = date;
}
public string getDate()
{
return datum;
}
public void setNotes(string notes)
{
dinota = notes;
}
public string getNotes()
{
return dinota;
}
private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
switch (tabControl1.SelectedIndex)
{
case 0:
{
//Nothing to do here
}
break;
case 1://tab containing where I want to display the data
misc.getConditions();
//MessageBox.Show("Conditions have been selected");
break;
}
}
public void printConditions()
{
MessageBox.Show(getdiagnosis()+"\t"+getDate()+"\t"+getNotes());
listConditions.Items.Add(getdiagnosis() + "\t" + getDate() + "\t" + getNotes());
}
}
The messagebox shows the requested data, but listbox listConditions does not, I do not know what is the problem.
PS: the messagebox was just to prove to myself that the requested data was indeed returned.
PPS: could you also suugest an alternative of specifying the connection string that doesn't require the absolute path to the solution.
I am testing my class. My method returns an array of insurance percentage paid and financial limit for the given policy id.
For policy id 43 its financial limit is null and its percentage insurance paid is 95.75.I am trying to test this but my test keep failing. Could any one tell where am doing wrong?
here is my class
public class PatientInsuranceLimits : System.Web.UI.Page
{
String sqlConStr = ConfigurationManager.ConnectionStrings["connectionname"].ToString();
public String[] generalLimits(String policyID)
{
String []resultset = new String[2];
SqlConnection con = new SqlConnection(sqlConStr);
String sqlQuery1 = "Select InsurancePaidPercentage as iPP, FinancialLimit as fLimit from Policy where ID=#poid";
SqlCommand cmd1 = new SqlCommand(sqlQuery1, con);
cmd1.Parameters.AddWithValue("#poid", policyID);
try
{
con.Open();
SqlDataReader r = cmd1.ExecuteReader();
while(r.Read()){
resultset[0] = r[0].ToString();
resultset[1] = r[1].ToString();
}
r.Close();
}
catch(Exception ex){
}
finally{
con.Close();
}
return resultset;
}
here is my test class
namespace _10_06_13_test
{
[TestClass()]
public class PatientInsuranceLimitsTest
{
private TestContext testContextInstance;
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
[DataSource("System.Data.SqlClient", "Data Source=servername_lab;Initial Catalog=IDKit;User ID=userid;Password=password", "mytable", DataAccessMethod.Sequential), TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("C:\\Users", "/")]
[UrlToTest("http://localhost:51063/")]
public void generalLimitsTest()
{
SurvivalHealth.PatientInsuranceLimits target = new SurvivalHealth.PatientInsuranceLimits();
string policyID = "43";
string[] expected = new string[] {"95.75"};
string[] actual;
actual = target.generalLimits(policyID);
Assert.AreEqual(expected, actual);
}
}
}
The function returns an array containing null and "19.75".
You need to change the value assigned to expected to { null, "19.75"}.
However if you are using .net 2 or later I would recommend that you change the method to return a tuple to prevent this sort of errors. It is probably also a good idea to store numbers in a numerical data type like decimal.
I have the following simple class to manage my SQL database operations
public class DatabaseManager
{
private string CommandString
{
set { CommandString = GetCommandString(commandtype); }
get { return CommandString; }
}
public string commandtype
{
set;
get;
}
public DatabaseManager(string commandtype)
{
commandtype = this.commandtype;
CommandString = GetCommandString(commandtype);
}
public DatabaseManager()
{
}
public static SqlConnection CreateConnection()
{
return new SqlConnection(Properties.Settings.Default.connectionString);
}
//returns a datatable if the command requires a dataadapter
public DataTable ExecuteSelect()
{
var x = new DataTable();
using (var da = new SqlDataAdapter(CommandString, DatabaseManager.CreateConnection()))
{
da.Fill(x);
}
return x;
}
private string GetCommandString(string commandtype)
{
switch (commandtype)
{
// select commands
case ("SELECTMARGINS"): CommandString = "select * from margins"; break;
case ("SELECTRANKS"): CommandString = "select * from ranks"; break;
/...and other commands
return CommandString;
}
}
i am getting a Stackoverflow exception on get { return CommandString; }
The get function is your problem
get { return CommandString; }
This is the morale equivalent of the following
public string GetCommandString() {
return GetCommandString();
}
This will just create infinite recursion and eventually a StackOverflowException will be thrown. You need to change the get and set to operate on a backing field which holds the actual value and use that instead
private string _commandString;
public string CommandString {
get { return _commandString; }
set { _commandString = GetCommandString(commandtype); }
}
You can't have a property return itself (it creates an infinite loop).
private string _CommandString;
public string CommandString
{
set { _CommandString = GetCommandString(commandtype); }
get { return _CommandString; }
}
You can't have a Get function return itself, it will just cause it to infinitely attempt to retrieve itself until the stack overflows.
Create a private variable to get and set to:
private string _CommandString;
private string CommandString
{
//Also you probably want to change commandtype to value, since you will be
//discarding whatever you attempt to set the variable as
set { _CommandString = GetCommandString(commandtype); }
get { return _CommandString; }
}
You cannot set or even get CommandString, you have to create a private variable in this case.
private string _commandString;
public string CommandString
{
set { _commandString = GetCommandString(commandtype); }
get { return _commandString; }
}
What is happening in your current code is that you are doing something like this:
CommandString = "x";
which calls
CommandString = GetCommandString(type);
which calls
CommandString = GetCommandString(type);
etc....so it keeps looping until it overflow. The private variable keeps you from setting the same property over and over again
Also, it looks like you are never actually using the value passed into the set function, which seems like a bug
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);