how to pass generic list parameter into a method? - c#

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?

Related

A Method with 2 Kind of Return Type

Ok, I have 3 classes: Teacher, Student and Database for that matter. I wanna read data from database and put it in Teacher or Student. So i have to write something like this:
public Teacher dbSelect(string Table="Teacher")
{
Table = char.ToUpper(Table[0]) + Table.Substring(1);
string query = "SELECT * FROM " + Table + ";";
return dbConnect(query, true);
}
But i must have this exact Method with Student return:
public Student dbSelect(string Table="Student")
{
Table = char.ToUpper(Table[0]) + Table.Substring(1);
string query = "SELECT * FROM " + Table + ";";
return dbConnect(query, true);
}
Now I can write each one in their ViewModel, But I want to put them in Database class. So is there any way to do that?
(I know i can return them in a list and then work with that list, But just wanna know if there is a way or not!)
UPDATE:
I forgot to put dbConnect in here, so:
public List<Teacher> dbConnect(string query)
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
Teacher result = new Teacher(null, null, null, null, null, null, null, null);
// try
{
conn = new SQLiteConnection(db.db);
conn.Open();
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
}
// catch (Exception ex) { }
while (reader.Read())
{
Teacher temp = new Teacher(
reader[0].ToString(),
reader[1].ToString(),
reader[2].ToString(),
reader[3].ToString(),
reader[4].ToString(),
reader[5].ToString(),
reader[6].ToString(),
reader[7].ToString()
);
result.Items.Add(temp);
}
conn.Close();
return result.Items;
}
And again the exact thing exist for Student but returning:
public List<Student> dbConnect(string query)
{
...
}
Answer: I had a Base class and of course wanted to return a List with a specific type, So I used #Jauch answer, but with returning the List.
Here is an idea on how to do what you want, adapted from a code of mine:
public class BaseClass<T>
where T : new ()
{
protected List<object> list;
protected string query;
protected PropertyInfo[] fProperties;
protected Assembly fStoreAssembly;
public BaseClass()
{
list = new List<T>();
fStoreAssembly = Assembly.GetAssembly (typeof(T));
fProperties = typeof(T).GetProperties();
}
public void Read()
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
try
{
conn = new SQLiteConnection(db.db);
conn.Open();
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
StoreResults (reader);
conn.Close();
}
catch (Exception ex)
{
//deal with the exception here
}
}
//Store results walks through all the records returned and
//creates new instances of the store object and saves in the list,
//using reflection
protected void StoreResults (SQLiteDataReader reader)
{
if (fProperties == null)
throw new Exception ("Store type definition is missing");
while (reader.Read ())
{
object newStoreItem = fStoreAssembly.CreateInstance (typeof(T).FullName);
foreach (PropertyInfo pi in fProperties)
{
string lcName = pi.Name.ToLower ();
if (HasColumn(reader, lcName))
{
if (!reader.IsDBNull(reader.GetOrdinal(lcName)))
pi.SetValue(newStoreItem, reader[lcName], null);
}
}
list.Add (newStoreItem);
}
}
public bool HasColumn (SQLiteDataReader reader, string columnName)
{
foreach (DataRow row in reader.GetSchemaTable().Rows)
{
if (row ["ColumnName"].ToString () == columnName)
return true;
}
return false;
}
}
And here how you would create Teacher and Student
public class TeacherInfo
{
//Properties for store info from database
}
public class Teacher : BaseClass<TeacherInfo>
{
public Teacher ()
: BaseClass()
{
query = "whatever you want here"
}
}
public class StudentInfo
{
//Properties for store info from database
}
public class Student : BaseClass<StudentInfo>
{
public Student ()
: BaseClass()
{
query = "whatever you want here";
}
}
As the Read routine is public, you can call Read from any instance of Teacher or Student.
You can even create them and store as BaseClass and use it directly if you don't need to know if it is a student or a teacher (for common routines, etc)
This is not an extensive example, but just a point in the direction you could use to turn your code more generic.
You can follow the semantics of using interfaces to return the values and then cast the return type to an appropriate one, or use a base class (interfaces would be better, as you can still extend other classes as base classes while implementing the interface). The entity interface can be created as following,
public interface SchoolEntity {
// Provide the similar properties as members of this interface.
}
Then you can implement this interface in your Teacher and Student.
public class Student : SchoolEntity { }
public class Teacher : SchoolEntity { }
Finally, the parameter can be made a bit more clearer by using enumerations. They would be more clearer while reading, rather than having the same parameter types. Note that function overloading doesn't consider return type as a signature difference.
enum Entity { Teacher, Student }
And then you can check which data to return.
public SchoolEntity dbSelect(Entity type)
{
switch(type) {
case Teacher:
var query = "SELECT * FROM Teacher";
return dbConnect(query, true);
// Rest of the cases.
}
}
Note that, your SQL statement is open to SQL Injection and anyone can either drop the tables, or perform actions that can be passed to the engine.
Working in a list
Working with the list won't be a good idea. Afterall, what list would you return? Would that be, public List<Teacher> dbSelect or public List<Student> dbSelect? The answer and solution to this is to have a same type backing up these both types.
dbSelect function
Note that you are still returning only Teacher type, then why you are having a Student at all? You should definitely cast it back. As a matter of fact, if I had to develop this. I would have to the dbSelect function to take the Entity as a parameter to keep all of the database requests and processing in a single function.
public List<Teacher> dbConnect(Entity type)
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
Teacher result = null; // Can be set to null.
// try
{
conn = new SQLiteConnection(db.db);
conn.Open();
string query;
// This way, leave the function to build the query.
if(type == Entity.Teacher) {
query = "SELECT * FROM Teacher";
} else {
query = "SELECT * FROM Student";
}
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
}
// catch (Exception ex) { }
while (reader.Read())
{
if(type == Entity.Teacher) {
Teacher temp = new Teacher(
reader[0].ToString(),
reader[1].ToString(),
reader[2].ToString(),
reader[3].ToString(),
reader[4].ToString(),
reader[5].ToString(),
reader[6].ToString(),
reader[7].ToString()
);
result.Items.Add(temp);
} else {
// Add the student.
}
}
conn.Close();
return result;
}
Now in this code, you are aware result is of type Teacher. There was no list there and this made your code a bit confusing. Take my advice: Re-write the code.
Please also go through the following useful links:
Explicit Interface Implementation
https://en.wikipedia.org/wiki/SQL_injection
Signatures and overloading

What is the most straightforward way to retrieve data from a local SQL Server database?

I don't need/want any security measures (username/password, etc.) - I just want to create a simple example of retrieving data from the AdventureWorks "lite" database (AdventureWorksLT2012_Data.mdf), storing that data in a generic list.
I have the following code to query an MS Access database. Would it be basically the same except for the connection string and query statement?
public SQLServerPOCRepository()
{
using (var conn = new OleDbConnection(
#"Provider=Microsoft.ACE.OLEDB.12.0;User ID=User;Password=Pass;Data Source=C:\SWin\DATA\SDAT42.MDB;Jet OLEDB:System database=C:\SWin\Data\wgeg.mdw"))
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT td_duckbill_accounts.dept_no, IIF(ISNULL(t_accounts.name),'No Name provided',t_accounts.name) AS name FROM t_accounts INNER JOIN td_duckbill_accounts ON t_accounts.account_no = td_duckbill_accounts.account_no ORDER BY td_duckbill_accounts.dept_no";
cmd.CommandType = CommandType.Text;
conn.Open();
int i = 1;
using (OleDbDataReader oleDbD8aReader = cmd.ExecuteReader())
{
while (oleDbD8aReader != null && oleDbD8aReader.Read())
{
int duckbillNum = oleDbD8aReader.GetInt16(0);
string duckbillName = oleDbD8aReader.GetString(1);
Add(new Platypus { Id = i, dbillNum = duckbillNum, Name = duckbillName });
i++;
}
}
}
}
}
The Add() method populates a generic list with an instance of the model Platypus class.
You need to update your connection string to use the System.Data.SqlClient provider, along with Integrated Security.
<add name="AdvWorksLT_ConnectionString"
connectionString="AttachDBFilename=C:\MyApplication\AdventureWorks.MDF;Integrated Security=True;User Instance=true"
providerName="System.Data.SqlClient"/>
Also, you need to use a SqlConnection, SqlCommand and SqlDataReader instead of the OleDbConnection, OleDbCommand, and OleDbDataReader.
You just need to set Integrated Security=True :
myConn = New SqlConnection("Initial Catalog=xxx.; Data Source=xxx; Integrated Security=True")
Sure, if you want to continue using OleDbConnection then you can just change the connection string and the query. That being said, it is better to use the ADO Sql Server Native Client. I believe Ole DB support for Sql Server is being deprecated, and 2012 will be the last version to officially support it:
http://technet.microsoft.com/en-us/library/ms130978.aspx
The way I prefer to do it is to create an method that accepts an IDataReader, and let that do the DataMapping/Serialization/Hydrating.
That allows the IDataReader to be created outside the code (Jet or Sql Server or Other), and then reused.
I also don't like "0", "1", etc.
Here is my typical IDataReader/DataMapper code. (See bigger code block later in this post)
As far as your original question, most DataTypes will match up.
However, I remember a few times between Jet and SqlServer, the datatypes were slightly off.
The workaround was use the GetValue(), and the cast it.
Instead of this:
decimal pubPrice = dataReader.GetDecimal(Layout.COLUMN0);
It ended up being like this:
decimal pubPrice = Convert.ToDecimal (accessDataReader.GetValue (Layout.COLUMN0));
Again, I was testing against an IDataReader being created against an OleDB (Jet/Access) vs Sql Server. I think I was testing with the pubs database, both the Jet(Access) version and the corresponding Sql Server version.
Most times it was fine. But once in a while I had to tweak and use the less "specific" "GetValue()" method, over the concrete getter (GetDecimal() for example).
[Serializable]
public partial class Employee
{
public int EmployeeKey { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public DateTime HireDate { get; set; }
}
[Serializable]
public class EmployeeCollection : List<Employee>
{
}
internal static class EmployeeSearchResultsLayouts
{
public static readonly int EMPLOYEE_KEY = 0;
public static readonly int LAST_NAME = 1;
public static readonly int FIRST_NAME = 2;
public static readonly int HIRE_DATE = 3;
}
public EmployeeCollection SerializeEmployeeSearchForCollection(IDataReader dataReader)
{
Employee item = new Employee();
EmployeeCollection returnCollection = new EmployeeCollection();
try
{
int fc = dataReader.FieldCount;//just an FYI value
int counter = 0;//just an fyi of the number of rows
while (dataReader.Read())
{
if (!(dataReader.IsDBNull(EmployeeSearchResultsLayouts.EMPLOYEE_KEY)))
{
item = new Employee() { EmployeeKey = dataReader.GetInt32(EmployeeSearchResultsLayouts.EMPLOYEE_KEY) };
if (!(dataReader.IsDBNull(EmployeeSearchResultsLayouts.LAST_NAME)))
{
item.LastName = dataReader.GetString(EmployeeSearchResultsLayouts.LAST_NAME);
}
if (!(dataReader.IsDBNull(EmployeeSearchResultsLayouts.FIRST_NAME)))
{
item.FirstName = dataReader.GetString(EmployeeSearchResultsLayouts.FIRST_NAME);
}
if (!(dataReader.IsDBNull(EmployeeSearchResultsLayouts.HIRE_DATE)))
{
item.HireDate = dataReader.GetDateTime(EmployeeSearchResultsLayouts.HIRE_DATE);
}
returnCollection.Add(item);
}
counter++;
}
return returnCollection;
}
//no catch here... see http://blogs.msdn.com/brada/archive/2004/12/03/274718.aspx
finally
{
if (!((dataReader == null)))
{
try
{
dataReader.Close();
}
catch
{
}
}
}
}

How to string a value across two functions?

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

return more than one data type

I query-ing this from entity framework using WCF, and i want to use the data in phone client side, may i know how can i query more than one data type from the WCF function ?
[OperationContract]
string LoginUser(string email, string password);
IService.cs
public string LoginUser(string email, string password)
{
string query = #"SELECT VALUE tblUser FROM MyEntities.tblUsers AS tblUser WHERE tblUser.email = #email AND tblUser.password = #password";
ObjectParameter[] parameters = new ObjectParameter[2];
parameters[0] = new ObjectParameter("email", email);
parameters[1] = new ObjectParameter("password", password);
using (var context = new SteamKingEntities())
{
ObjectQuery<string> results = context.CreateQuery<string>(query, parameters);
foreach (string result in results)
{
if (result != null)
{
return result;
}
}
}
return null;
}
IService.svc.cs
public Login()
{
InitializeComponent();
_serviceClient = new Service1Client();
_serviceClient.LoginUserCompleted += new EventHandler<LoginUserCompletedEventArgs>(_serviceClient_LoginUserCompleted);
}
private void loginBtn_Click(object sender, RoutedEventArgs e)
{
_serviceClient.LoginUserAsync(txtEmail.Text, txtPassword.Password);
}
private void _serviceClient_LoginUserCompleted(object sender, LoginUserCompletedEventArgs e)
{
if (e.Error == null && e.Result != null)
{
MessageBox.Show("Welcome " + e.Result + "!");
}
else
{
MessageBox.Show(e.Error.Message + " Couldn't Login, Please try again =D");
}
}
Login.xaml.cs
I want to return the entire table from Entity Framework and allow me to process one by one in Window Phone side.
I guess i need to do some modification to the IService side but i seriously don't know how because i'm new to phone development and used to Linq to SQL. Can you please guide me on how to make something like type for the return, Please. Thank you.
Update
The error i get There was an error while trying to deserialize parameter http://tempuri.org/:LoginUserResult. Please see InnerException for more details.
i was modified the code into the way stated in WCF Custom Object but i could not deserialize it... i guess the problem came from the WP part, how could i deserialize the result ?
You can use ref or you can use custom-objects
You need to use data contract:
[DataContract]
public class ReturnType
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Pass { get; set; }
}
in service it would look like this:
[OperationContract]
Entities.ReturnType[] SelectTopUser(int countOfTop);
the return type can be an entity framework type

c# property won't work?

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);

Categories