Click here to Skip to main content
15,843,144 members
Please Sign up or sign in to vote.
2.87/5 (4 votes)
See more:
In this sample code (C# winForms app) there is a `Employee` class with `SearchEmployee()` method and a `DataService` class with `GetByEmployeeID()` method. When searching for a employee, `SearchEmployee(`) method will call `GetByEmployeeID()` method to talk to database. I have minimized the dependency between `Employee` class and `DataService` class by using constructor injection. (in its simplest way with out using an Interface)

But there is a dependency between `Form` class and `Employee` class as I `new` employee object from `From` class.

Will that dependency be a problem or isn't?

If that dependency should be avoided, What is the simplest way to achieve this?
Appreciate if you could answer with code.

I prefer not to use a pattern like MVP as I'm not familiar with it.

C#
Class Form
    {
        public Form()
        {
            InitializeComponents();
        }
    
            private void btnSave_Click(object sender, EventArgs e)
            {
                    Employee newEmp = new Employee (new DataService()); //Making a dependency 
                    newEmp = newEmp.SearchEmployee (txtEmployeeID.Text);
                    txtEmployeeName.Text = newEmp.EmployeeName;
                    txtEmployeeAddress.Text = newEmp.EmployeeAddress;
            }
    }
    
    
    Class Employee
    {
            string EmployeeID  { get; set; }
            string EmployeeName { get; set; }
            string EmployeeAddress { get; set; }
    
            DataService _DS;
    
            public Employee(DataService DS) //Constructor injection of dataservice object
            {
                this._DS = DS;
            }
    
            public Employee SearchEmployee (string employeeID)
            {
                this.EmployeeID  =employeeID;
    
                DataTable DT= _DS.GetByEmployeeID(EmployeeID);
                this.EmployeeName = DT.Rows[0].ItemArray[1].ToString();
                this.EmployeeAddress = DT.Rows[0].ItemArray[2].ToString();
    
                return this; //Returning an employee object to the caller
            }
    }
    
    
    //This class responsible for database transaction
    
     class DataService
        {
    
            public DataTable GetByEmployeeID(string employeeID)
            {
                using (SqlConnection newCon = new SqlConnection(db.GetConnectionString))
                {
                    SqlCommand Cmd = new SqlCommand("SELECT..WHERE emp_id=@employeeID", newCon);
                    Cmd.Parameters.Add("@employeeID", SqlDbType.varChar).Value = employeeID;
                    newCon.Open();
                    SqlDataReader rdr = Cmd.ExecuteReader();
                    DataTable results = new DataTable();
                    results.Load(rdr);
    
                    return results;
                }
            }
        }
Posted
Updated 15-Apr-14 0:36am
v3

To take advantage of loose coupling, I suggest you to change your design and use MVC like this;

C#
[STAThread]
static void Main()
{
	Application.EnableVisualStyles();
	Application.SetCompatibleTextRenderingDefault(false);

	var view = new FormMain();
	var controller = new Controller(view, new EmployeeManager(new DataService()));

	Application.Run(view);
}


public partial class FormMain : Form
{
	private Controller _controller;

	public FormMain()
	{
		InitializeComponent();
	}

	public void SetController(Controller controller)
	{
		_controller = controller;
	}

	private void button1_Click(object sender, EventArgs e)
	{
		var newEmp = _controller.SearchEmployee(txtEmployeeID.Text);
                if(null == newEmp) 
                {
                   //Id is not found.
                }
		txtEmployeeName.Text = newEmp.EmployeeName;
		txtEmployeeAddress.Text = newEmp.EmployeeAddress;
	}
}

public class Controller
{
	private FormMain _view;
	private EmployeeManager _manager;


	public Controller(FormMain view, EmployeeManager manager)
	{
		_view = view;
		_manager = manager;
		view.SetController(this);
	}

	public Employee SearchEmployee(string employeeID)
	{
	   return _manager.SearchEmployee(employeeID);
	}

	private void UpdateService(DataService newService)
	{
		_manager = new EmployeeManager(newService);
	}

}

public class EmployeeManager
{

	private DataService _ds;

	public EmployeeManager(DataService DS)
	{
		_ds = DS;
	}

	public Employee SearchEmployee(string employeeID)
	{

		var dt = _ds.GetByEmployeeId(employeeID);

		if (dt.Rows.Count > 0)
		{

			return new Employee(employeeID,
								dt.Rows[0].ItemArray[1].ToString(),
								dt.Rows[0].ItemArray[2].ToString());
		}
		return null;
	}

	//ADD DELETE UPDATE METHODS etc.

}

public class Employee
{
	public string EmployeeID { get; set; }
	public string EmployeeName { get; set; }
	public string EmployeeAddress { get; set; }


	public Employee(string employeeID, string employeeName, string employeeAddress)
	{
		EmployeeID = employeeID;
		EmployeeName = employeeName;
		EmployeeAddress = employeeAddress;
	}
}

public class DataService
{
	public DataTable GetByEmployeeId(string employeeID)
	{
		using (SqlConnection newCon = new SqlConnection(""))
		{
			SqlCommand Cmd = new SqlCommand("SELECT..WHERE emp_id=@employeeID", newCon);
			Cmd.Parameters.Add("@employeeID", SqlDbType.VarChar).Value = employeeID;
			newCon.Open();
			SqlDataReader rdr = Cmd.ExecuteReader();
			DataTable results = new DataTable();
			results.Load(rdr);
			return results;
		}
	}
}
 
Share this answer
 
v2
Comments
Chathur 15-Apr-14 23:59pm    
Could you please clarify why you have put this code as follows instead of putting it in the constructor of FormMain? Also when this method is get invoked?

public void SetController(Controller controller)
{
_controller = controller;
}
Emre Ataseven 16-Apr-14 0:55am    
It is invoked in the constructor of controller
view.SetController(this);

When you create your controller with form, created object is set as controller of form. And we don't need controller to able to create form but form for controller.
Chathur 16-Apr-14 6:29am    
If I eliminate controller class and if use MainForm's constructor to reference an EmployeeManger object as follows, Obviously now its not MVC but do you see any other draw backs ?

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

var EmployeeManager= new EmployeeManager(new DataService());
var view = new FormMain(EmployeeManager);


Application.Run(view);
}


public partial class FormMain : Form
{
private Controller _controller;

public FormMain(EmployeeManager employeemanager)
{
InitializeComponent();
_employeemanager= employeemanager;
}


private void button1_Click(object sender, EventArgs e)
{
var newEmp = _employeemanager.SearchEmployee(txtEmployeeID.Text);
if(null == newEmp)
{
//Id is not found.
}
txtEmployeeName.Text = newEmp.EmployeeName;
txtEmployeeAddress.Text = newEmp.EmployeeAddress;
}
}



public class EmployeeManager
{

private DataService _ds;

public EmployeeManager(DataService DS)
{
_ds = DS;
}

public Employee SearchEmployee(string employeeID)
{

var dt = _ds.GetByEmployeeId(employeeID);

if (dt.Rows.Count > 0)
{

return new Employee(employeeID,
dt.Rows[0].ItemArray[1].ToString(),
dt.Rows[0].ItemArray[2].ToString());
}
return null;
}

//ADD DELETE UPDATE METHODS etc.

}

public class Employee
{
public string EmployeeID { get; set; }
public string EmployeeName { get; set; }
public string EmployeeAddress { get; set; }


public Employee(string employeeID, string employeeName, string employeeAddress)
{
EmployeeID = employeeID;
EmployeeName = employeeName;
EmployeeAddress = employeeAddress;
}
}

public class DataService
{
public DataTable GetByEmployeeId(string employeeID)
{
using (SqlConnection newCon = new SqlConnection(""))
{
SqlCommand Cmd = new SqlCommand("SELECT..WHERE emp_id=@employeeID", newCon);
Cmd.Parameters.Add("@employeeID", SqlDbType.VarChar).Value = employeeID;
newCon.Open();
SqlDataReader rdr = Cmd.ExecuteReader();
DataTable results = new DataTable();
results.Load(rdr);
return results;
}
}
}
Emre Ataseven 16-Apr-14 6:41am    
As Vedat said,we shouldn't use concrete objects as dependency. To ease things, I used FormMain as parameter to construct controller. We should do it like this for abstraction;

public partial class FormMain : Form, IView
...

And

Controller(IView view,...

public Interface IView
{
void SetController(Controller controller);
}



Emre Ataseven 16-Apr-14 6:47am    
And your design has some flaws;
You are creating your Form with EmployeeManager but don't need to do it in this condition, seems useless. You can really create this object in FormMain class, no need this constructor.
good point. I advice you to take a look to MEF[^]. one of the best questions I have seen in these days, by the way.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900