I am consuming Wcf Service in Windows Form Application . I am trying to create user login system based on user emu type from sql database .When I enter the value 1 into textbox it should return full time employee method else value 2 into textbox it should return part time employee method but Its is not working according expectation ..
Here is Employee class code ....
[KnownType(typeof(FullTimeEmployee))]
[KnownType(typeof(PartTimeEmployee))]
[DataContract(Namespace = "http://pragimtech.com/Employee")]
public class Employee
{
private int _id;
private string _name;
private string _gender;
private DateTime _dateOfBirth;
[DataMember(Order = 1)]
public int Id
{
get { return _id; }
set { _id = value; }
}
[DataMember(Order = 2)]
public string Name
{
get { return _name; }
set { _name = value; }
}
[DataMember(Order = 3)]
public string Gender
{
get { return _gender; }
set { _gender = value; }
}
[DataMember(Order = 4)]
public DateTime DateOfBirth
{
get { return _dateOfBirth; }
set { _dateOfBirth = value; }
}
[DataMember(Order = 5)]
public EmployeeType Type { get; set; }
}
[DataContract(Name = "EmployeeType")]
public enum EmployeeType
{
[EnumMember]
FullTimeEmployee = 1,
[EnumMember]
PartTimeEmployee = 2
}
}
Here is my Full time and part time employee class inherit from Employee class...
public class FullTimeEmployee : Employee
{
public int AnnualSalary { get; set; }
}
public class PartTimeEmployee : Employee
{
public int HourlyPay { get; set; }
public int HoursWorked { get; set; }
}
Here is Method to Get Employee method to access employee based on employee type...
public Employee GetEmployee(int Id)
{
Employee employee = null;
string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("spGetEmployee1", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter parameterId = new SqlParameter();
parameterId.ParameterName = "#EmployeeType";
parameterId.Value = Id;
cmd.Parameters.Add(parameterId);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
if ((EmployeeType)reader["EmployeeType"] == EmployeeType.FullTimeEmployee)
{
return employee;
} }
else if ((EmployeeType)reader["EmployeeType"] == EmployeeType.PartTimeEmployee)
{
return employee;
}
}
}
return employee;
}
Here is my Windows Form Application ......
private void button1_Click(object sender, EventArgs e)
{
MyService.HalifaxServiceClient myservice = new MyService.HalifaxServiceClient("NetTcpBinding_IHalifaxService");
MyService.Employee employee = myservice.GetEmployee(Convert.ToInt32(txt1.Text));
MyService.FullTimeEmployee ft = new MyService.FullTimeEmployee();
if (employee == myservice.GetEmployee(Convert.ToInt32(txt1.Text).CompareTo(employee.Type)))
{
FulltimeEmployeeLinkActivites();
}
else if (employee == myservice.GetEmployee(Convert.ToInt32(txt1.Text).CompareTo(employee.Type)))
{
PartTimeEmployeeActivities();
}
else
{
label4.Text = "No infomation found";
}
}
Here is screen shot when I run the application ...
The problem I see with your if / else is that the conditional statements are exactly the same. One way that you can branch based on the type of an object is with the is keyword.
if (employee is FullTimeEmployee)
{
FulltimeEmployeeLinkActivites();
}
else if (employee is PartTimeEmployee)
{
PartTimeEmployeeActivities();
}
else
{
label4.Text = "No information found";
}
I would also add that this is not necessarily best practice, however it should get you what you are asking for.
In addition to that, your method that returns the employee instance never returns an employee of a valid type. It doesn't appear that the GetEmployee method ever instantiates an employee instance. It looks like it is always returning null. Try returning instances of the proper type. You will also need to populate the instances with the data you need.
if ((EmployeeType)reader["EmployeeType"] == EmployeeType.FullTimeEmployee)
{
return new FullTimeEmployee();
}
else if ((EmployeeType)reader["EmployeeType"] == EmployeeType.PartTimeEmployee)
{
return new PartTimeEmployee();
}
You have a confusing naming in your elements and "employee" class does not seems to be populated in your data reader.
"FullTimeEmployee" is the name one of your classes and also the name of one of your enums. So is not safe to set your condition
(EmployeeType)reader["EmployeeType"] == EmployeeType.FullTimeEmployee
I can not be sure without the code of your spGetEmployee, but if it returns values from your table with those same names it could be safer to declare
while(reader.Read())
{
employee= new employee();
employee.Id= reader.GetInt32(0);
employee.Name= reader.GetString(1);
...
employee.EmployeeType=(EmployeeType)reader.GetInt32(4);
if(employee.EmployeeType== EmployeeType.FullTimeEmployee)
{
//Do extra work for this type of employee
...
return employee;
}
}
Related
I am consuming wcf service into console application . I am trying to retrieve account information based on account number . But the problem is when i enter the account number and hit enter ,its only displaying account number and rest of the fields are empty.
Here is the base class.
[DataContract]
public class Current_Account_Details
{
string account_creation_date;
string account_type;
string branch_sort_code;
string account_fees;
string account_balance;
string over_draft_limit;
string account_holder_id;
[DataMember]
public string Account_Creation_Date
{
get { return account_creation_date; }
set { account_creation_date = value; }
}
[DataMember]
public string Account_Type
{
get { return account_type; }
set { account_type = value; }
}
[DataMember]
public string Branch_Sort_Code
{
get { return branch_sort_code; }
set { branch_sort_code = value; }
}
[DataMember]
public string Account_Fees
{
get { return account_fees; }
set { account_fees = value; }
}
[DataMember]
public string Account_Balance
{
get { return account_balance; }
set { account_balance = value; }
}
[DataMember]
public string Over_Draft_Limit
{
get { return over_draft_limit; }
set { over_draft_limit = value; }
}
[DataMember]
public string Account_Holder_Id
{
get { return account_holder_id; }
set { account_holder_id = value; }
}
}
}
Here is the inherited class.
[DataContract]
public class AccountBalanceRequest : Current_Account_Details
{
string account_number;
[DataMember]
public string Account_Number
{
get { return account_number; }
set { account_number = value; }
}
}
}
Here is the Interface .
[OperationContract]
AccountBalanceRequest AccountBalanceCheek(AccountBalanceRequest accountNumber);
Here is my Method .
public AccountBalanceRequest AccountBalanceCheek(AccountBalanceRequest accountNumber)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
//use top 1 since you are only getting one record.
//let us use string interpolation, if you are working below C#6
//replace it with your previous value
var cmd = new SqlCommand($#"SELECT TOP 1
*
FROM
Current_Account_Details
WHERE
Account_Number ='{accountNumber.Account_Number}'", conn);
cmd.CommandType = CommandType.Text;
//use ExecuteReader to execute sql select
//ExecuteNonQuery is for update, delete, and insert.
var reader = cmd.ExecuteReader();
//read the result of the execute command.
while (reader.Read())
{
//assuming that your property is the same as your table schema. refer to your table schema Current_Account_Details
//assuming that your datatype are string... just do the conversion...
accountNumber.Account_Balance = reader["Account_Balance"].ToString();
accountNumber.Account_Fees = reader["Account_Fees"].ToString();
accountNumber.Account_Balance = reader["Account_Balance"].ToString();
accountNumber.Over_Draft_Limit = reader["Over_Draft_Limit"].ToString();
}
return accountNumber;
}
}
Here is the code in Console Application .
public static void Balance()
{
MyService.HalifaxCurrentAccountServiceClient currentAccount = new MyService.HalifaxCurrentAccountServiceClient("NetTcpBinding_IHalifaxCurrentAccountService");
MyService.AccountBalanceRequest cs = new MyService.AccountBalanceRequest();
string AccountNumber;
Console.WriteLine("\nEnter your Account Number--------:");
AccountNumber = Console.ReadLine();
cs.Account_Number = AccountNumber;
// MyService.AccountBalanceRequest cs1 = currentAccount.AccountBalanceCheek(AccountNumber);
MyService.AccountBalanceRequest AccountBalance = currentAccount.AccountBalanceCheek(cs);//error on this line
Console.WriteLine("Account Number is :" + cs.Account_Number);
Console.WriteLine("Account creation date :" + cs.Account_Creation_Date);
Console.WriteLine("Account Type :" + cs.Account_Type);
Console.WriteLine("Branch_Sort_Code:" + cs.Branch_Sort_Code);
Console.WriteLine("Account_Fee:" + cs.Account_Fees);
Console.WriteLine("Account Account_Balance :" + cs.Account_Balance);
Console.WriteLine("Account Over Draft Limit :" + cs.Over_Draft_Limit);
Console.Write("--------------------------");
Console.ReadLine();
//Console.Clear();
}
Here is the screen shot of the database.click here to record
Here is the screen shot when i run the applicationClick here to see the result.In this screen shot only the account number is displaying and rest of the fields are empty
your Current_Account_Details is the base class and AccountBalanceRequest is derived class from your question posted.
If we have classes related by inheritance, the wcf service generally accepts and returns the base type. If you expect the service to accept and return inherited types, then use KnownType attribute.
So its enough if you decorate the base class with contracts and try.
[KnownType(typeof(AccountBalanceRequest))]
[DataContract]
public class Current_Account_Details
{
string account_creation_date;
string account_type;
string branch_sort_code;
string account_fees;
string account_balance;
string over_draft_limit;
string account_holder_id;
[DataMember]
public string Account_Creation_Date
{
get { return account_creation_date; }
set { account_creation_date = value; }
}
[DataMember]
public string Account_Type
{
get { return account_type; }
set { account_type = value; }
}
[DataMember]
public string Branch_Sort_Code
{
get { return branch_sort_code; }
set { branch_sort_code = value; }
}
[DataMember]
public string Account_Fees
{
get { return account_fees; }
set { account_fees = value; }
}
[DataMember]
public string Account_Balance
{
get { return account_balance; }
set { account_balance = value; }
}
[DataMember]
public string Over_Draft_Limit
{
get { return over_draft_limit; }
set { over_draft_limit = value; }
}
[DataMember]
public string Account_Holder_Id
{
get { return account_holder_id; }
set { account_holder_id = value; }
}
}
}
public class AccountBalanceRequest : Current_Account_Details
{
string account_number;
public string Account_Number
{
get { return account_number; }
set { account_number = value; }
}
}
Just check whether account number that you read from console is passed in the accountnumber variable.
var cmd = new SqlCommand("SELECT * FROM Current_Account_Details WHERE Account_Number = '" + accountNumber + "'", conn);
Edit 1: Your service is failing to retrieve records because you are passing the AccountBalanceRequest object and the changes made to the object is not reflected outside the method.
MyService.AccountBalanceRequest cs = new MyService.AccountBalanceRequest();
Change it to.
public AccountBalanceRequest AccountBalanceCheek(AccountBalanceRequest accountNumber)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
//use top 1 since you are only getting one record.
//let us use string interpolation, if you are working below C#6
//replace it with your previous value
var cmd = new SqlCommand($#"SELECT TOP 1
*
FROM
Current_Account_Details
WHERE
Account_Number ='{accountNumber.Account_Number}'", conn));
cmd.CommandType = CommandType.Text;
//use ExecuteReader to execute sql select
//ExecuteNonQuery is for update, delete, and insert.
var reader = cmd.ExecuteReader();
//read the result of the execute command.
while(reader.Read())
{
//assuming that your property is the same as your table schema. refer to your table schema Current_Account_Details
//assuming that your datatype are string... just do the conversion...
accountNumber.Account_Balance = reader["Account_Balance"].ToString();
accountNumber.Account_Fee = reader["Account_Fee"].ToString();
accountNumber.Account_Balance = reader["Account_Balance"].ToString();
accountNumber.Over_Draft_Limit = reader["Over_Draft_Limit"].ToString();
}
return accountNumber;
}
}
In your console retrieve it,
MyService.AccountBalanceRequest AccountBalance =currentAccount.AccountBalanceCheek(cs);
Console.WriteLine("Your Account Number is :" + cs.Account_Number)
...
I think your problem is that you're passing a reference to the WCF service method and changing it there instead of returning. The documentation says that:
Each operation has a return value and a parameter, even if these are void. However, unlike a local method, in which you can pass references to objects from one object to another, service operations do not pass references to objects. Instead, they pass copies of the objects.
Try to change your code so the method returns the changed object. At the end of AccountBalanceCheek method instead of returning true return accountNumber.
And then in Balance method - remove if statement and change to:
....
cs = currentAccount.AccountBalanceCheek(cs);
Console.WriteLine("Your Account Number is :" + cs.Account_Number);
Console.WriteLine("Your Account Type :" + cs.Account_Balance);
....
To read more about it: Is it possible to pass parameters by reference with WCF
I am consuming a WCF service in a Windows Forms application. My WCF service has two classes called FulltimeEmployee and ParttimeEmployee. I want to register users into Sql database by using Wcf Service with Windows Fomr Application based on employee type. The user type will come from emu type but I can not compile it and showing following errors ...
Non-invocable member 'EmployeeType.FullTimeEmployee' cannot be used like a method. HalifaxWindowsFormsApplication C:\Users\Khundokar Nirjor\Documents\Visual Studio 2015\Projects\HalifaxWindowsFormsApplication\HalifaxWindowsFormsApplication\ADDEMPLOYEE.cs 38 Active
as shown in the screen shot.
Here is Code for FullTime and PartTime Employee Class..
[DataContract]
public class FullTimeEmployee : Employee
{
public int AnnualSalary { get; set; }
}
[DataContract]
public class PartTimeEmployee : Employee
{
public int HourlyPay { get; set; }
public int HoursWorked { get; set; }
}
Here is the code form class..
[KnownType(typeof(FullTimeEmployee))]
[KnownType(typeof(PartTimeEmployee))]
[DataContract(Namespace = "http://pragimtech.com/Employee")]
public class Employee
{
private int _id;
private string _name;
private string _gender;
private DateTime _dateOfBirth;
[DataMember(Order = 1)]
public int Id
{
get { return _id; }
set { _id = value; }
}
[DataMember(Order = 2)]
public string Name
{
get { return _name; }
set { _name = value; }
}
[DataMember(Order = 3)]
public string Gender
{
get { return _gender; }
set { _gender = value; }
}
[DataMember(Order = 4)]
public DateTime DateOfBirth
{
get { return _dateOfBirth; }
set { _dateOfBirth = value; }
}
[DataMember(Order = 5)]
public EmployeeType Type { get; set; }
}
public enum EmployeeType
{
FullTimeEmployee = 1,
PartTimeEmployee = 2
}
}
Here is WCF service code to register employee based on type:
public void SaveEmployee(Employee employee)
{
string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("spSaveEmployee", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter parameterId = new SqlParameter
{
ParameterName = "#Id",
Value = employee.Id
};
cmd.Parameters.Add(parameterId);
SqlParameter parameterName = new SqlParameter
{
ParameterName = "#Name",
Value = employee.Name
};
cmd.Parameters.Add(parameterName);
SqlParameter parameterGender = new SqlParameter
{
ParameterName = "#Gender",
Value = employee.Gender
};
cmd.Parameters.Add(parameterGender);
SqlParameter parameterDateOfBirth = new SqlParameter
{
ParameterName = "#DateOfBirth",
Value = employee.DateOfBirth
};
cmd.Parameters.Add(parameterDateOfBirth);
SqlParameter parameterEmployeeType = new SqlParameter
{
ParameterName = "#EmployeeType",
Value = employee.Type
};
cmd.Parameters.Add(parameterEmployeeType);
if (employee.GetType() == typeof(FullTimeEmployee))
{
SqlParameter parameterAnnualSalary = new SqlParameter
{
ParameterName = "#AnnualSalary",
Value = ((FullTimeEmployee)employee).AnnualSalary
};
cmd.Parameters.Add(parameterAnnualSalary);
}
else
{
SqlParameter parameterHourlyPay = new SqlParameter
{
ParameterName = "#HourlyPay",
Value = ((PartTimeEmployee)employee).HourlyPay,
};
cmd.Parameters.Add(parameterHourlyPay);
SqlParameter parameterHoursWorked = new SqlParameter
{
ParameterName = "#HoursWorked",
Value = ((PartTimeEmployee)employee).HoursWorked
};
cmd.Parameters.Add(parameterHoursWorked);
}
con.Open();
cmd.ExecuteNonQuery();
}
}
Here is the Windows Form application code:
private void button1_Click(object sender, EventArgs e)
{
MyService.HalifaxServiceClient myservice = new MyService.HalifaxServiceClient("NetTcpBinding_IHalifaxService");
MyService.Employee employee = null;
if (((MyService.EmployeeType)Convert.ToInt32(comboBox2.SelectedValue)) == MyService.EmployeeType.FullTimeEmployee)
{
employee = new MyService.FullTimeEmployee
{
Id = Convert.ToInt32(textBox1.Text),
Name = txtName.Text,
Gender = comboBox1.Text,
DateOfBirth = Convert.ToDateTime(txtDateOfBirth.Text),
Type = MyService.EmployeeType.FullTimeEmployee(comboBox2.SelectedValue),//Error
AnnualSalary = Convert.ToInt32(txtAnnualSalary.Text),
};
myservice.SaveEmployee(employee);
label8.Text = "Employee saved";
}
else if (((MyService.EmployeeType)Convert.ToInt32(comboBox2.SelectedValue)) == MyService.EmployeeType.PartTimeEmployee)
{
employee = new MyService.PartTimeEmployee
{
Id = Convert.ToInt32(textBox1.Text),
Name = txtName.Text,
Gender = comboBox1.Text,
DateOfBirth = Convert.ToDateTime(txtDateOfBirth.Text),
Type = MyService.EmployeeType.PartTimeEmployee(comboBox2.SelectedValue),//Error
HourlyPay = Convert.ToInt32(txtHourlyPay.Text),
HoursWorked = Convert.ToInt32(txtHoursWorked.Text),
};
myservice.SaveEmployee(employee);
label8.Text = "Employee saved";
}
else
{
label8.Text = "Please select Employee Type";
}
}
private void button2_Click(object sender, EventArgs e)
{
this.Close();
}
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox2.Text == "FullTimeEmployee")
{
txtHourlyPay.Visible = false;
txtHoursWorked.Visible = false;
label6.Visible = false;
label7.Visible = false;
}
else if (comboBox2.Text == "PartTimeEmployee")
{
txtHourlyPay.Visible = true;
txtHoursWorked.Visible = true;
label6.Visible = true;
label7.Visible = true;
}
}
When I click the submit button its shows the error message
and does not insert a new employee into SQL Server database..
Here is screenshot of output:
Please help me to correct this error ...
You'll need to mark your enum with [DataContract] attribute and each enum value with [EnumMember] attribute like this. I also noticed that you've got your enum members as knowntypes on the Employee data contract and not the enum itself.
[DataContract]
public class Car
{
[DataMember]
public string model;
[DataMember]
public CarConditionEnum condition;
}
[DataContract(Name = "CarCondition")]
public enum CarConditionEnum
{
[EnumMember]
New,
[EnumMember]
Used,
[EnumMember]
Rental,
Broken,
Stolen
}
For more information checkout this link
Edit: Here's what you're looking for. You should try something like:
Type = (MyService.EmployeeType) Enum.Parse(typeof(MyService.EmployeeType), comboBox2.SelectedText);
I want to assign a List to a member variable (the variable is a List), but I always get error message: System.StackOverflowException was unhandled, I don't know why, please see my code below:
public class Employee
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public int DeptID { get; set; }
}
public class Department
{
public int DeptID { get; set; }
public string DeptName { get; set; }
public List<Employee> Employees
{
set { Employees = value; }
//get { return EmployeeDataAccessLayer.getEmployeesByDeptID(DeptID); }
get { return Employees; }
}
}
public class EmployeeDataAccessLayer
{
public static List<Employee> getEmployeesByDeptID(int deptID)
{
string conStr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
string sqlStr = "select * from tblemployee where deptid = :deptid order by employeeid asc";
List<Employee> employees = new List<Employee>();
using (OracleConnection ocon = new OracleConnection(conStr))
{
OracleCommand ocmd = new OracleCommand(sqlStr, ocon);
ocmd.Parameters.Add(":deptid", deptID);
ocmd.Connection.Open();
OracleDataReader rdr = ocmd.ExecuteReader();
while (rdr.Read())
{
Employee employee = new Employee();
employee.EmployeeID = Convert.ToInt32(rdr["EMPLOYEEID"]);
employee.EmployeeName = rdr["NAME"].ToString();
employee.DeptID = Convert.ToInt32(rdr["DEPTID"]);
employees.Add(employee);
}
}
return employees;
}
}
public class DepartmentDataAccessLayer
{
public static List<Department> getAllDepartments()
{
string conStr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
string sqlStr = "select * from tbldepartment order by departmentid asc";
List<Department> depts = new List<Department>();
using (OracleConnection ocon = new OracleConnection(conStr))
{
OracleCommand ocmd = new OracleCommand(sqlStr, ocon);
ocmd.Connection.Open();
OracleDataReader rdr = ocmd.ExecuteReader();
while (rdr.Read())
{
Department dept = new Department();
dept.DeptID = Convert.ToInt32(rdr["DEPARTMENTID"]);
dept.DeptName = rdr["NAME"].ToString();
dept.Employees = EmployeeDataAccessLayer.getEmployeesByDeptID(dept.DeptID);
depts.Add(dept);
}
}
return depts;
}
}
so, I debug it and found the exception occured at:
set { Employees = value;}
see below screenshot:
I really don't know why, can you tell me the reason or give me some suggestions?
In your case, when you assign something to the Employees it's setter will trigger it again assigns to the same variable so the same process will continues and it's leads to a infinity assignments, that's why you are getting that Exception. to overcome this Change the property definition like this:
private List<Employee> _Employees
public List<Employee> Employees
{
set { _Employees = value; }
get { return _Employees; }
}
or like this:
public List<Employee> Employees { get; set; }
Because you're setting Employees to value which is setting Employees to value which is setting Employees to value which is setting.......etc etc until the stack overflows.
Because you're not using a private variable to hold employees, you can just use an auto-getter and -setter to set the value to itself, like your other properties:
public List<Employee> Employees { get; set; }
Otherwise, setup a private variable to hold the list of employees. This can be use
private List<Employee> _employees;
public List<Employee> Employees
{
set { _employees = value; }
get { return _employees; }
}
If you're setting a value in C# with get and set, all you'll need to do is
public List<Employee> Employees{get; set;}
With an empty get and set block, the value will be assigned automatically. In your code, you're essentially calling the set function for your variable over and over again until a StackOverflow exception occurs
More information on properties here
I am trying to insert data into a database using a three-tier architecture, but I am stuck and I cannot proceed further.
This is my code
First is UI part:
public void assignField()
{
string maritalCondition = "";
string sex = "";
assignObj.Registered_Date = dateTimePicker1_Date.Value;
assignObj.First_Name = txt_FirstName.Text;
if (comboBox2_MaritalStatus.SelectedIndex == 0)
{
maritalCondition = "Single";
}
else
maritalCondition = "Married";
assignObj.Marital_Status = maritalCondition;
if (RadioButton_Male.Checked == true)
sex = "Male";
else
sex = "Female";
assignObj.Gender = sex;
this.txt_Age.Text = Convert.ToInt32(age).ToString();
}
private void btnRegister_Click(object sender, EventArgs e)
{
assignField();
}
Next is the middle tier:
public class CustomerDataType
{
private DateTime registered_Date;
private string first_Name;
private int age;
private string marital_Status;
private string gender;
public DateTime Registered_Date
{
get { return registered_Date; }
set { registered_Date = value; }
}
public string First_Name
{
get { return first_Name; }
set { first_Name = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
public string Marital_Status
{
get { return marital_Status; }
set { marital_Status = value; }
}
public string Gender
{
get { return gender; }
set { gender = value; }
}
public void insertInfo()
{
CustomerDataAccess insertObj = new CustomerDataAccess(Registered_Date, First_Name, Age, Marital_Status, Gender);
insertObj.insertCustomerInfo();
}
}
and last is the data access tier:
public class CustomerDataAccess
{
public CustomerDataAccess(DateTime Registered_Date, string First_Name, int Age, string Marital_Status, string Gender)
{
this.registrationDate = Registered_Date;
this.fName = First_Name;
this.userAge = Age;
this.marriageStatus = Marital_Status;
this.userGender = Gender;
}
SqlConnection con;
SqlCommand cmd;
DateTime registrationDate;
string fName = "";
int userAge;
string marriageStatus;
string userGender;
public void insertCustomerInfo()
{
try
{
con = new SqlConnection("Data Source=LAKHE-PC;Initial Catalog=Sahakari;Integrated Security=True");
con.Open();
cmd = con.CreateCommand();
cmd.CommandText = "sp_registerCust";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Registered_Date", SqlDbType.DateTime);
cmd.Parameters["#Registered_Date"].Value = registrationDate;
cmd.Parameters.Add("#First_Name", SqlDbType.VarChar);
cmd.Parameters["#First_Name"].Value = fName;
cmd.Parameters.Add("#Age", SqlDbType.Int.ToString());
cmd.Parameters["#Age"].Value = userAge;
cmd.Parameters.Add("#Marital_Status", SqlDbType.VarChar);
cmd.Parameters["#Marital_Status"].Value = marriageStatus;
cmd.Parameters.Add("#Gender", SqlDbType.VarChar);
cmd.Parameters["#Gender"].Value = userGender;
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Here with the stored procedure, there is no problem and and from SQL Server I can insert data into table easily. But from windows form, it does not insert data in table. Plz help me.
I'll do something like below
UI
CustomerHandler custHandler = new CustomerHandler();
// create Customer object and pass to insert method
if (custHandler.InsertCustomer(new Customer(){
FirstName = txt_FirstName.Text, Registered_Date =dateTimePicker1_Date.Value,
//decalare other parameters....
))
{
// insert Success, show message or update label with succcess message
}
In my BL
public class CustomerHandler
{
// in BL you may have to call several DAL methods to perform one Task
// here i have added validation and insert
// in case of validation fail method return false
public bool InsertCustomer(Customer customer)
{
if (CustomerDataAccess.Validate(customer))
{
CustomerDataAccess.insertCustomer(customer);
return true;
}
return false;
}
}
In MY DAL
// this is the class you going to use to transfer data across the layers
public class Customer
{
public DateTime Registered_Date { get; set; }
public string FirstName { get; set; }
//so on...
}
public class CustomerDataAccess
{
public static void insertCustomer(Customer customer)
{
using (var con = new SqlConnection("Data Source=LAKHE-PC;Initial Catalog=Sahakari;Integrated Security=True"))
using (var cmd = con.CreateCommand())
{
con.Open();
cmd.CommandText = "sp_registerCust";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Registered_Date", customer.Registered_Date);
cmd.Parameters.AddWithValue("#FirstName", customer.FirstName);
// so on...
cmd.ExecuteNonQuery();
}
}
internal static bool Validate(Customer customer)
{
// some validations before insert
}
}
Your middle tier consists of classes holding the values you require in properties. Instead of writing the data access manually, try using the Entity Framework (EF) which does that for you.
Here (at MSDN) you can find a quickstart example which shows you how you can use it.
Instead of mapping the fields manually and executing a query, the Entity Framework does that which means you just have to assign the values to the object's properties and call SaveChanges() - the SQL code is created and executed automatically by the EF.
For further reading, there is also a lot to find here (at Stackoverflow).
In my program I have a list of marks and a dictionary which stores the studentId. I want that the user enters the studentId and according to that id it will point to the list of marks. I think I am implementing it incorrectly. Can someone help me in implementing it. Thanks
public class Student() {
private string name;
private string surname;
private string dob;
private string address;
private int id;
public Student()
{
}
public Student(string year,string name, string surname, string dob, string address)
{
this.name = name;
this.surname = surname;
this.dob = dob;
this.address = address;
this.year = year;
}
public string Name
{
get { return name; }
set { name = value; }
}
public string Surname
{
get { return surname; }
set { surname = value; }
}
public string DOB
{
get { return dob; }
set { dob = value; }
}
public string Addr
{
get { return address; }
set { address = value; }
}
public int Id
{
get { return id; }
set { id = value; }
}
private string year;
public string Year
{
get { return year; }
set { year = value; }
}
public Student(string s)
{
string[] splitted = s.Split(',');
name = splitted[0];
surname = splitted[1];
dob = splitted[2];
address = splitted[3];
// id = splitted[4];
}
public Dictionary<int,List<Marks>> dictionary= new Dictionary<int,List<Marks>>();
public List<Marks> Mathematics = new List<Marks>();
public List<Marks> English = new List<Marks>();
public List<Marks> Maltese = new List<Marks>();
public List<Marks> ReligiousStudies = new List<Marks>();
public List<Marks> SocialStudies = new List<Marks>();
public Dictionary<int, List<Marks>> dictionar = new Dictionary<int, List<Marks>>();
public void AddMarks(int hyexam, int anexam)
{
{
Console.WriteLine("enter id of student to input marks to:");
string id = Console.ReadLine();
if (dictionar.ContainsKey(Id).Equals(id))
{
Mathematics.Add(new Marks(hyexam, anexam));
English.Add(new Marks(hyexam, anexam));
Maltese.Add(new Marks(hyexam, anexam));
ReligiousStudies.Add(new Marks(hyexam, anexam));
SocialStudies.Add(new Marks(hyexam, anexam));
dictionar.Add(id, (Mathematics)); //dont know how to implement it
}
else
{
Console.WriteLine("id not found");
}
}
}
public class Marks
{
private int hyexam;
private int anexam;
private string id;
public int HYEXAM
{
get { return hyexam; }
set { hyexam = value; }
}
public int ANEXAM
{
get { return anexam; }
set { anexam = value; }
}
public string Id
{
get { return id; }
set { id = value; }
}
public Marks(int hyexam, int anexam)
{
this.hyexam = hyexam;
this.anexam = anexam;
}
public Marks(string id)
{
this.id = id;
}
public double OverallExam()
{
return (0.4 * hyexam) + (0.6 * anexam);
}
}
}
I'd say the main problem is your modelling. You've included the Dictionary<int, List<Marks>> as a field within Student. That means that each Student object has a dictionary. That makes no sense - because the key for the dictionary is meant to be the student ID, right?
It probably makes sense for each Student object to the lists of marks as you've currently got (although not as public fields, IMO). Given that information, do you really need a Dictionary going to the marks at all? Wouldn't it be cleaner to have a Dictionary<int, Student> somewhere (not in the Student class - maybe in a School class?) mapping each student ID to a Student, and you can get the marks from the Student?
Think hard about what you're trying to achieve, and where the data really belongs. In my experience, when you've got the data modelling right, the code usually follows in a clean way.
(I'd also question your Marks class, both in terms of name and design. What are those properties meant to represent? Isn't it really a single mark in an exam? Perhaps ExamResult would be clearer? Does it really need to be mutable?)
I'd agree with Jon that this is definitely a modeling issue (based on the OP's other posts). If you're new to object oriented programming, the first thing you need to do is determine what objects you'll need to create to answer the problem.
What is a Student? A student has a name, id, dob, class year, etc. For every attribute a student has, you need to set up a field or property.
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime DoB { get; set; }
... etc ...
}
What is a Mark? From your descriptions, a Mark has a subject, a mid-exam score, and an annual-exam score.
public class Mark
{
public string Subject { get; set; }
public int MidScore { get; set; }
public int FinalScore { get; set; }
}
What is the relationship between a Student and a Mark? A student has a list of marks associated with them. This is best described with a List<> object.
public class Student() // continued
{
public List<Mark> Marks { get; set; }
}
Once you have the basics set up for your objects, it will be easier to filter out what you DON'T need, and make it much easier to answer your question. :)
My proposal:
Your "Mark" class must have something that identifies the subject (could be an enum called Subject, or an string, or an int with the ID of the subject if you have it stored in database)
Then you could have:
Console.WriteLine("enter id of student to input marks to:");
string id = Console.ReadLine();
var marks = new Dictionary<int, List<Mark>>();
if (UserExists(id))
{
Console.WriteLine("mark for subject1:");
string s1 = Console.ReadLine();
Console.WriteLine("mark for subject2:");
string s2 = Console.ReadLine();
var list = new List<Mark>();
list.Add(new Mark { Subject = SubjectEnum.Subject1, Value = Convert.ToDecimal(s1), });
list.Add(new Mark { Subject = SubjectEnum.Subject2, Value = Convert.ToDecimal(s2), });
marks.Add(Convert.ToInt32(id), list)
}
else
{
Console.WriteLine("id not found");
}
Hope this helps.