473,396 Members | 2,076 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

design pattern of "Business Layer"

Hi , i am trying to figure out which approach is better to use .
let me explain the scenario.
i am using the "Nortwind" database . in this database i have "Customers "
table .The following is the two different ways to handle this table.

CASE 1 :
create a struct that encaplusates table "Customers" columns
public struct structCustomers
{
public string CustomerID;
public string CompanyName;
public string ContactName;
public string ContactTitle;
public string Address;
public string City;
public string Region;
public string PostalCode;
public string Country;
public string Phone;
public string Fax;
public Customers(int i) {
// assign variables to their default whatever they are
CustomerID = -1 ; CompanyName ="";
}
}
And write a class that encaplusates table
public class Customers {
// all methods related to stored procedures about table
public SqlDataReader GetAllCustomers()
{
.....
return sqlcommand.executereader("GetCustomers",.....)
}
}

and if a need to pass parameters to a method i am using the following ,
lets say as an illustration
public SqlDataReader InsertCustomerDetails(structCustomers sc )
{
sqlparameter customerid = new sqlparameter ("@custid",
Sqldbtype.varchar)
customerid.Value = sc.CustomerID ;
.....
return sqlcommand.executereader("GetCustomers",.....)
}

and finally from calling UI i have the following
void button1_click()
{
structCustomers sc = new structCustomers(0);
sc.CustomerID = textbox1.text ;
Customers c = new Customers ();
dataset ds = c.GetCustomerDetail (sc);
}
CASE 2 :

write a class that encaplusates all table related info
public class Customers {

public string m_CustomerID;
public string m_CompanyName;
public string m_ContactName;
public string m_ContactTitle;
public string m_Address;
public string m_City;
public string m_Region;
public string m_PostalCode;
public string m_Country;
public string m_Phone;
public string m_Fax;

// write all set and get
public object CustomerID{
set
{
m_CustomerID= value;
}
get
{
return m_CustomerID;
}
}

// all methods related to stored procedures about table
public SqlDataReader GetAllCustomers()
{
.....
return sqlcommand.executereader("GetCustomers",.....)
}
}

and if a need to pass parameters to a method i am using the following ,
lets say as an illustration
public SqlDataReader InsertCustomerDetails()
{
sqlparameter customerid = new sqlparameter ("@custid",
Sqldbtype.varchar)
customerid.Value = this.m_CustomerID;
.....
return sqlcommand.executereader("GetCustomers",.....)
}

and finally from calling UI i have the following
void button1_click()
{
Customers c = new Customers ();
c.CustomerID = textbox1.text ;
dataset ds = c.GetCustomerDetail ();
}

these are the different ways i know. Which one is better to use ? Comments
are welcome , and valuable.

not : the different approaches has their disadvantages, dont care about so
much .as an example " get the customers who live either country "Canada" or
"Turkey" , anyway maybe keep this situation for further discussions
Nov 17 '05 #1
8 1212
Good question, Hassan.

There are a couple of principles involved here. One is that a business class
should "mind its own business." That is, a business class should contain
whatever functionality is necessary to work with it, and expose whatever may
be necessary to any client class that may need it. the first model
unnecessarily puts a structure into a class that contains the processes
needed to work on the structure. The "outer" class isn't doing anything but
working with Customer classes. You call it "Customers," but in fact, the
code is for woking with a single "Customer." A class encapsulates data and
process, and there is no need for one class to contain the data, and another
to contain the process. Obviously, we're looking at a thin slice of what a
"Customer" might do, and in fact, there would be much more process involved.
For example, the structure members could be private fields exposed using
public properties. These public properties could then contain process for
doing things like validation. After all, the length of the database field
for "CompanyName," for example, is limited in length. A public Setter could
throw an exception if the value input was too long. And so on. This way, the
Customer class would manage itself.

So, in a sense, your second model is better. However, I would take it a step
further, with a Data Layer. Consider your database function:
// all methods related to stored procedures about table
public SqlDataReader GetAllCustomers()
{
.....
return sqlcommand.executereader("GetCustomers",.....)
}
}
and your UI code:
void button1_click()
{
structCustomers sc = new structCustomers(0);
sc.CustomerID = textbox1.text ;
Customers c = new Customers ();
dataset ds = c.GetCustomerDetail (sc);
}
First, the Customer class has members which expose database data in an
object-oriented way. The class represents a "Customer." It is an object
which represents an entity, not an object which represents anything to do
with a database. So, why would it make sense for it to expose a DataReader,
especially since a DataReader must be closed, and the Connection with it?

In fact, the UI layer shouldn't even be aware that it is working with a
database. It should be aware that it is working with a Customer object. If
it needs the CompanyName, it gets it from the CompanyName property of the
class. Etc. the UI's job is to present a "Customer" entity to a user in a
user-friendly manner. And the business class's job is to present Customer
data to the UI and other business objects in a programmer-friendly manner.

So, first, the Customer class, in order to "mind its own business," should
only expose fields and properties pertaining to a Customer to client
classes.

But there's more. In that database function, what I see abstractly is a
function that executes a query or stored procedure, and returns a
SqlDataReader. Sounds like a potentially reusable function to me, with a
little tweaking. How about a Data class with a static function like the
following?

public static SqlDataReader GetDataReader(SqlConnection conn,
SqlCommand command, string ProcedureName,
ParamArray params)
{
OpenConn(conn, command);
.....
return lcommand.ExecuteReader(ProcedureName, params);
}

Just a rough idea. You would have to flesh out the details yourself, of
course, including how to handle the ConnectionString, etc.

Now, the Customer class is the only class that will probably using this
Stored Procedure, so it will know the Procedure name and the parameters
needed. So, you have a method that populates the class from the Stored
Procedure, such as a Constructor method. Example:

public Customer(string CustomerID)
{
try
{
SqlCommand command;
SqlConnection conn;
SqlDataReader dr;
ParamArray params = ...;
dr = DataClass.GetDataReader(conn, command, "GetCustomer", params);
...
_CustomerID = dr.GetString(dr.GetOrdinal("CustomerID"));
...
}
catch (Exception ex)
{...}
finally
{
dr.Close();
DataClass.CloseConn(conn, command);
}
}

Now the DataClass class encapsulates database functionality, and the
Customer class encapsulates all the process necessary to create a Customer
with a simple API. Any UI class can simply create an instance of a Customer
by passing the ID

That's the power of object-orientation!

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
Ambiguity has a certain quality to it.

"Hasan O. Zavalsiz" <ho********@gmail.com> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl... Hi , i am trying to figure out which approach is better to use .
let me explain the scenario.
i am using the "Nortwind" database . in this database i have "Customers "
table .The following is the two different ways to handle this table.

CASE 1 :
create a struct that encaplusates table "Customers" columns
public struct structCustomers
{
public string CustomerID;
public string CompanyName;
public string ContactName;
public string ContactTitle;
public string Address;
public string City;
public string Region;
public string PostalCode;
public string Country;
public string Phone;
public string Fax;
public Customers(int i) {
// assign variables to their default whatever they are
CustomerID = -1 ; CompanyName ="";
}
}
And write a class that encaplusates table
public class Customers {
// all methods related to stored procedures about table
public SqlDataReader GetAllCustomers()
{
.....
return sqlcommand.executereader("GetCustomers",.....)
}
}

and if a need to pass parameters to a method i am using the following ,
lets say as an illustration
public SqlDataReader InsertCustomerDetails(structCustomers sc )
{
sqlparameter customerid = new sqlparameter ("@custid",
Sqldbtype.varchar)
customerid.Value = sc.CustomerID ;
.....
return sqlcommand.executereader("GetCustomers",.....)
}

and finally from calling UI i have the following
void button1_click()
{
structCustomers sc = new structCustomers(0);
sc.CustomerID = textbox1.text ;
Customers c = new Customers ();
dataset ds = c.GetCustomerDetail (sc);
}
CASE 2 :

write a class that encaplusates all table related info
public class Customers {

public string m_CustomerID;
public string m_CompanyName;
public string m_ContactName;
public string m_ContactTitle;
public string m_Address;
public string m_City;
public string m_Region;
public string m_PostalCode;
public string m_Country;
public string m_Phone;
public string m_Fax;

// write all set and get
public object CustomerID{
set
{
m_CustomerID= value;
}
get
{
return m_CustomerID;
}
}

// all methods related to stored procedures about table
public SqlDataReader GetAllCustomers()
{
.....
return sqlcommand.executereader("GetCustomers",.....)
}
}

and if a need to pass parameters to a method i am using the following ,
lets say as an illustration
public SqlDataReader InsertCustomerDetails()
{
sqlparameter customerid = new sqlparameter ("@custid",
Sqldbtype.varchar)
customerid.Value = this.m_CustomerID;
.....
return sqlcommand.executereader("GetCustomers",.....)
}

and finally from calling UI i have the following
void button1_click()
{
Customers c = new Customers ();
c.CustomerID = textbox1.text ;
dataset ds = c.GetCustomerDetail ();
}

these are the different ways i know. Which one is better to use ?
Comments
are welcome , and valuable.

not : the different approaches has their disadvantages, dont care about so
much .as an example " get the customers who live either country "Canada"
or
"Turkey" , anyway maybe keep this situation for further discussions

Nov 17 '05 #2
Hi Hasan,

I will prefer the second approach. As the first one is is structure and
they have there limitation. But the best approach would be the hybrid
approach encapsulate the structure inside the class.

Thats mean
class x
{
structure customer
{
string customer;
}

}
And use the properties to set the structure.
-------
Regards ,
C#, VB.NET , SQL SERVER , UML , DESIGN Patterns Interview question book
http://www.geocities.com/dotnetinterviews/
My Interview Questions Blog
http://spaces.msn.com/members/dotnetinterviews/

Nov 17 '05 #3
"Hasan O. Zavalsiz" <ho********@gmail.com> a écrit dans le message de news:
%2****************@TK2MSFTNGP09.phx.gbl...

| Hi , i am trying to figure out which approach is better to use .
| let me explain the scenario.
| i am using the "Nortwind" database . in this database i have "Customers "
| table .The following is the two different ways to handle this table.

Modelling a class based on a table is never as good an idea as modelling
your class and then providing a table to persist the data of instances of
that class.

In the example Customer table, the Contact details are mixed in with the
Customer(Company) details; this is the first indicator that badly normalised
tables are not a good starting point for well designed classes (a Company
can have more than one Contact)

Good OO practice suggests that you separate your business logic completely
from your data layer, so you could start by having a Contact class :

public interface IIdentifiable
{
int ID { get, set };
}

Start off by separating the concept of identity from anything else, after
all, you should not either use anything other than an integer for a primary
key in a database table nor should that key have any business meaning. Now a
Customer may well have a reference code that could be alphanumeric but that
would be in addition to any unique integer used for database keys.

public class Contact : IIdentifiable
{
private int id;
private string name;
private string title;

int IIdentifiable.ID
{
get { return id; }
set { id = value; }
}

public string Name
{
get { return name; }
set { name = value; }
}

public string Title
{
get { return title; }
set { title = value; }
}
}

Note that the id field in the Contact class is an integer and that it is not
surfaced as a public property, instead it can only be accessed from outside
the class through the IIdentifiable interface. This is a deterrent to using
the ID in everyday code as it will only really be wanted by the persistence
mechanism that stores and retrieves instances of your Contact class. It is
unlikely that you would need a readable reference code for each Contact, so
that has been omitted from the class.

The Customer class will be similar, but there are one or two aspects that
will differ, both from the Contact class and also a "normal" database table
:

public class Customer : IIdentifiable
{
private int id;
private string ref;
private string name;
private string address;
private string city;
private string region;
private string postalCode;
private string country;
private string phone;
private string fax;

... // public properties

private List<Contact> contacts;

public Enumerator<Contact> Contacts
{
get { return contacts.GetEnumerator(); }
}

public Contact AddContact()
{
contacts.Add(new Contact());
}

public void RemoveContact(Contact contact)
{
contacts.Remove(contact);
}
}

It would possibly be necessary to include a Customer Ref property so a
string field and property would be added for this.

Notice that we are keeping the Contacts list hidden and only allowing adding
or removing of Contacts via methods; if you need the list of Contacts, then
you can only get an enumerator to the internal list.

Also note that we don't have a "foreign key" to the Customer in the Contact
class as would be normal for a 1-n relationship in a relational database.
Instead the Customer has a list of Contacts.

It would be the job of a data access layer to translate this object
relationship to the RDB relationship, but the business classes need know
nothing of this matter.

You would then look at a data access layer whose job it is to take any
object that supports IIdentifiable and use reflection to persist/retrieve
the data for that particular object, using the "hidden" ID as the database
table primary or foreign keys.

public class ObjectStore
{
public bool StoreObject(IIdentifiable obj)
{
// extract ID from the interface, then cast to Object and use reflection
// to extract the property values
// Then create a SQL Insert or Update statement using the values
}

...
}

Just as you would only ever expect a set of records to be returned from a
database, so you should never expect a retrieval of objects from an Object
Store to only return one object. A Retrieval method on the ObjectStore class
should return a List which you can then traverse in the normal manner. .NET
datagrids are just as capable of displaying properties of objects as they
are of displaying fields of tables.

Using this technique gives you the flexibility to change your database
vendor without having to change any of your business coding; the only
changes wouldf be to the SQL generated and the query component created to
handle that SQL.

For further reading on OPFs (Object Persistence Frameworks) go to my website
www.carterconsulting.org.uk; the articles are written for a Delphi audience,
but the principles are the same.

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Nov 17 '05 #4
Hi Kevin ,
thanks for the answer. I have made some comments about your ideas , inline .

So, in a sense, your second model is better. However, I would take it a step further, with a Data Layer. Consider your database function:
// all methods related to stored procedures about table
public SqlDataReader GetAllCustomers()
{
.....
return sqlcommand.executereader("GetCustomers",.....)
}
}
and your UI code:
void button1_click()
{
structCustomers sc = new structCustomers(0);
sc.CustomerID = textbox1.text ;
Customers c = new Customers ();
dataset ds = c.GetCustomerDetail (sc);
}


First, the Customer class has members which expose database data in an
object-oriented way. The class represents a "Customer." It is an object
which represents an entity, not an object which represents anything to do
with a database. So, why would it make sense for it to expose a

DataReader, especially since a DataReader must be closed, and the Connection with it?

it is just a psoude code , i generally use facade modeling ( using ms
enterprise library , data access app. block )

In fact, the UI layer shouldn't even be aware that it is working with a
database. It should be aware that it is working with a Customer object. If
it needs the CompanyName, it gets it from the CompanyName property of the
class. Etc. the UI's job is to present a "Customer" entity to a user in a
user-friendly manner. And the business class's job is to present Customer
data to the UI and other business objects in a programmer-friendly manner.

So, first, the Customer class, in order to "mind its own business," should
only expose fields and properties pertaining to a Customer to client
classes.

I got the idea. if i need the all customers , i cant get it xx proterty , it
a dataset/datatable or something. Do I handle this situation and similar
situations using an private DataSet ? and return like

void button1_click()
{
structCustomers sc = new structCustomers(0);
sc.CustomerID = textbox1.text ;
Customers c = new Customers ();
c.GetCustomers();
dataset ds = c.dsCustomersAll;
}

But there's more. In that database function, what I see abstractly is a
function that executes a query or stored procedure, and returns a
SqlDataReader. Sounds like a potentially reusable function to me, with a
little tweaking. How about a Data class with a static function like the
following?

public static SqlDataReader GetDataReader(SqlConnection conn,
SqlCommand command, string ProcedureName,
ParamArray params)
{
OpenConn(conn, command);
.....
return lcommand.ExecuteReader(ProcedureName, params);
}

Just a rough idea. You would have to flesh out the details yourself, of
course, including how to handle the ConnectionString, etc.

The idea is telling me that i have been on the right way already , i am
using facade pattern and ms entirprise library . I dont create commands,
connection strings .
every class or only one connection is open for general use .
Now, the Customer class is the only class that will probably using this
Stored Procedure, so it will know the Procedure name and the parameters
needed. So, you have a method that populates the class from the Stored
Procedure, such as a Constructor method. Example:

public Customer(string CustomerID)
{
try
{
SqlCommand command;
SqlConnection conn;
SqlDataReader dr;
ParamArray params = ...;
dr = DataClass.GetDataReader(conn, command, "GetCustomer", params); ...
_CustomerID = dr.GetString(dr.GetOrdinal("CustomerID"));
...
}
catch (Exception ex)
{...}
finally
{
dr.Close();
DataClass.CloseConn(conn, command);
}
}

Now the DataClass class encapsulates database functionality, and the
Customer class encapsulates all the process necessary to create a Customer
with a simple API. Any UI class can simply create an instance of a Customer by passing the ID

That's the power of object-orientation!

--
HTH,

Kevin Spencer
Microsoft MVP
.Net Developer
Ambiguity has a certain quality to it.

Again thanks for the answer Kevin ,
have a nice day
Nov 17 '05 #5
Hi shiv ,
do i need a struct if already handled with private objects ?

<sh**********@yahoo.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Hi Hasan,

I will prefer the second approach. As the first one is is structure and
they have there limitation. But the best approach would be the hybrid
approach encapsulate the structure inside the class.

Thats mean
class x
{
structure customer
{
string customer;
}

}
And use the properties to set the structure.
-------
Regards ,
C#, VB.NET , SQL SERVER , UML , DESIGN Patterns Interview question book
http://www.geocities.com/dotnetinterviews/
My Interview Questions Blog
http://spaces.msn.com/members/dotnetinterviews/

Nov 17 '05 #6
Hi Joanna ,

"Joanna Carter [TeamB]" <jo****@not.for.spam> wrote in message
news:uR**************@TK2MSFTNGP09.phx.gbl...
"Hasan O. Zavalsiz" <ho********@gmail.com> a écrit dans le message de news: %2****************@TK2MSFTNGP09.phx.gbl...

| Hi , i am trying to figure out which approach is better to use .
| let me explain the scenario.
| i am using the "Nortwind" database . in this database i have "Customers " | table .The following is the two different ways to handle this table.

Modelling a class based on a table is never as good an idea as modelling
your class and then providing a table to persist the data of instances of
that class.
modelling that i use is based on the principles of " how is " , "has it " ,
"owns it" . I mean the customer table in on the top of related table .
Customers has orders , has contact and so on .
Joanna
Joanna Carter [TeamB]
Consultant Software Engineer


thanks for the answer , let me think about what you have written
have a nice day
Nov 17 '05 #7
Glad to be of service, Hasan.
I got the idea. if i need the all customers , i cant get it xx proterty ,
it
a dataset/datatable or something. Do I handle this situation and similar
situations using an private DataSet ? and return like
I figured my example might be a little confusing, due to its handling only
one Customer. but I was trying to keep things short, sweet, and to the
point. The same principle would apply when dealing with, for example,
getting a subset of Customers from the Customers table in the database. What
you would need would be 2 things:

1. A CustomerCollection class. This class would be a Collection, with a
method or methods for populating it with Customer objects. Since each
Customer is a class unto itself, you would want a Collection for handling
groups of Customers for various purposes, such as populating them all at
once from a single query, applying a business rule across the entire subset,
etc.

2. An overload for the Customer constructor. In fact, it might not be
necessary to have an overload for the Customer constructor that takes a
Customer ID and performs a query, but the nice thing about overloads is that
you can overload them! ;-) For example, keeping in mind that business
objects should "mind their own business," you could create an overload for a
Customer constructor that takes an ID and a dataset:

public Customer(string customerID, DataSet ds)
{
foreach (DataRow dr in ds.Tables["Customer"].Rows)
if ((string)dr["CustomerID"] == customerID)
{
CustomerID = customerID;
...
}
break;
}

This way the Customer populates itself from a data source passed to it by
the CustomerCollection. This way the CustomerCollection can populate itself
by looping through the rows of a table in a DataSet (for example), getting
the CustomerID value from the row, and adding a new Customer class to its
List, passing the CustomerID and DataSet to the Customer constructor.

I used a DataSet as an example, because the DataSet can house multiple
tables, and there might be a relationship between the Customer table and
another table, such that the Customer might need access to the other table
when being populated. Another advantage to the DataSet is that the
CustomerCollection could keep a cached copy of the data for doing updates.

But one of the beauties of the CLR is its immense flexibility. You can
customize your app to use whatever combination of available classes and
methodology suits its requirements. In other words, this is a rough idea,
for the purpose of illustrating the concept, not a recommended methodology
for a specific purpose.
The idea is telling me that i have been on the right way already , i am
using facade pattern and ms entirprise library . I dont create commands,
connection strings .
every class or only one connection is open for general use .
One caveat here: It is not a good idea to keep Connections opened. The .Net
platform makes excellent use of Connection Pooling. When you use the same
Connection String to open a Connection, it is re-used from the pool, if it
has been used before. Keeping Connections opened in .Net defeats the purpose
of Connection Pooling, which is there for a number of good reasons. Think of
Connections like File streams. Open them and close them as quickly as
possible. Cache your Connection String, and re-use it instead.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
Ambiguity has a certain quality to it.

"Hasan O. Zavalsiz" <ho********@gmail.com> wrote in message
news:O9**************@TK2MSFTNGP14.phx.gbl... Hi Kevin ,
thanks for the answer. I have made some comments about your ideas , inline
.

So, in a sense, your second model is better. However, I would take it a

step
further, with a Data Layer. Consider your database function:
> // all methods related to stored procedures about table
> public SqlDataReader GetAllCustomers()
> {
> .....
> return sqlcommand.executereader("GetCustomers",.....)
> }
> }


and your UI code:
> void button1_click()
> {
> structCustomers sc = new structCustomers(0);
> sc.CustomerID = textbox1.text ;
> Customers c = new Customers ();
> dataset ds = c.GetCustomerDetail (sc);
> }


First, the Customer class has members which expose database data in an
object-oriented way. The class represents a "Customer." It is an object
which represents an entity, not an object which represents anything to do
with a database. So, why would it make sense for it to expose a

DataReader,
especially since a DataReader must be closed, and the Connection with it?


it is just a psoude code , i generally use facade modeling ( using ms
enterprise library , data access app. block )

In fact, the UI layer shouldn't even be aware that it is working with a
database. It should be aware that it is working with a Customer object.
If
it needs the CompanyName, it gets it from the CompanyName property of the
class. Etc. the UI's job is to present a "Customer" entity to a user in a
user-friendly manner. And the business class's job is to present Customer
data to the UI and other business objects in a programmer-friendly
manner.

So, first, the Customer class, in order to "mind its own business,"
should
only expose fields and properties pertaining to a Customer to client
classes.


I got the idea. if i need the all customers , i cant get it xx proterty ,
it
a dataset/datatable or something. Do I handle this situation and similar
situations using an private DataSet ? and return like

void button1_click()
{
structCustomers sc = new structCustomers(0);
sc.CustomerID = textbox1.text ;
Customers c = new Customers ();
c.GetCustomers();
dataset ds = c.dsCustomersAll;
}

But there's more. In that database function, what I see abstractly is a
function that executes a query or stored procedure, and returns a
SqlDataReader. Sounds like a potentially reusable function to me, with a
little tweaking. How about a Data class with a static function like the
following?

public static SqlDataReader GetDataReader(SqlConnection conn,
SqlCommand command, string ProcedureName,
ParamArray params)
{
OpenConn(conn, command);
.....
return lcommand.ExecuteReader(ProcedureName, params);
}

Just a rough idea. You would have to flesh out the details yourself, of
course, including how to handle the ConnectionString, etc.


The idea is telling me that i have been on the right way already , i am
using facade pattern and ms entirprise library . I dont create commands,
connection strings .
every class or only one connection is open for general use .
Now, the Customer class is the only class that will probably using this
Stored Procedure, so it will know the Procedure name and the parameters
needed. So, you have a method that populates the class from the Stored
Procedure, such as a Constructor method. Example:

public Customer(string CustomerID)
{
try
{
SqlCommand command;
SqlConnection conn;
SqlDataReader dr;
ParamArray params = ...;
dr = DataClass.GetDataReader(conn, command, "GetCustomer",

params);
...
_CustomerID = dr.GetString(dr.GetOrdinal("CustomerID"));
...
}
catch (Exception ex)
{...}
finally
{
dr.Close();
DataClass.CloseConn(conn, command);
}
}

Now the DataClass class encapsulates database functionality, and the
Customer class encapsulates all the process necessary to create a
Customer
with a simple API. Any UI class can simply create an instance of a

Customer
by passing the ID

That's the power of object-orientation!

--
HTH,

Kevin Spencer
Microsoft MVP
.Net Developer
Ambiguity has a certain quality to it.

Again thanks for the answer Kevin ,
have a nice day

Nov 17 '05 #8
Hi Kevin ,

why ms dont give such an example :)
thanks a lot

"Kevin Spencer" <ke***@DIESPAMMERSDIEtakempis.com> wrote in message
news:eR**************@TK2MSFTNGP15.phx.gbl...
Glad to be of service, Hasan.
I got the idea. if i need the all customers , i cant get it xx proterty , it
a dataset/datatable or something. Do I handle this situation and similar
situations using an private DataSet ? and return like
I figured my example might be a little confusing, due to its handling only
one Customer. but I was trying to keep things short, sweet, and to the
point. The same principle would apply when dealing with, for example,
getting a subset of Customers from the Customers table in the database.

What you would need would be 2 things:

1. A CustomerCollection class. This class would be a Collection, with a
method or methods for populating it with Customer objects. Since each
Customer is a class unto itself, you would want a Collection for handling
groups of Customers for various purposes, such as populating them all at
once from a single query, applying a business rule across the entire subset, etc.

2. An overload for the Customer constructor. In fact, it might not be
necessary to have an overload for the Customer constructor that takes a
Customer ID and performs a query, but the nice thing about overloads is that you can overload them! ;-) For example, keeping in mind that business
objects should "mind their own business," you could create an overload for a Customer constructor that takes an ID and a dataset:

public Customer(string customerID, DataSet ds)
{
foreach (DataRow dr in ds.Tables["Customer"].Rows)
if ((string)dr["CustomerID"] == customerID)
{
CustomerID = customerID;
...
}
break;
}

This way the Customer populates itself from a data source passed to it by
the CustomerCollection. This way the CustomerCollection can populate itself by looping through the rows of a table in a DataSet (for example), getting
the CustomerID value from the row, and adding a new Customer class to its
List, passing the CustomerID and DataSet to the Customer constructor.

I used a DataSet as an example, because the DataSet can house multiple
tables, and there might be a relationship between the Customer table and
another table, such that the Customer might need access to the other table
when being populated. Another advantage to the DataSet is that the
CustomerCollection could keep a cached copy of the data for doing updates.

But one of the beauties of the CLR is its immense flexibility. You can
customize your app to use whatever combination of available classes and
methodology suits its requirements. In other words, this is a rough idea,
for the purpose of illustrating the concept, not a recommended methodology
for a specific purpose.
The idea is telling me that i have been on the right way already , i am
using facade pattern and ms entirprise library . I dont create commands, connection strings .
every class or only one connection is open for general use .
One caveat here: It is not a good idea to keep Connections opened. The

..Net platform makes excellent use of Connection Pooling. When you use the same
Connection String to open a Connection, it is re-used from the pool, if it
has been used before. Keeping Connections opened in .Net defeats the purpose of Connection Pooling, which is there for a number of good reasons. Think of Connections like File streams. Open them and close them as quickly as
possible. Cache your Connection String, and re-use it instead.

HTH,

Kevin Spencer
Microsoft MVP
.Net Developer
Ambiguity has a certain quality to it.

"Hasan O. Zavalsiz" <ho********@gmail.com> wrote in message
news:O9**************@TK2MSFTNGP14.phx.gbl...
Hi Kevin ,
thanks for the answer. I have made some comments about your ideas , inline .

So, in a sense, your second model is better. However, I would take it a

step
further, with a Data Layer. Consider your database function:

> // all methods related to stored procedures about table
> public SqlDataReader GetAllCustomers()
> {
> .....
> return sqlcommand.executereader("GetCustomers",.....)
> }
> }

and your UI code:

> void button1_click()
> {
> structCustomers sc = new structCustomers(0);
> sc.CustomerID = textbox1.text ;
> Customers c = new Customers ();
> dataset ds = c.GetCustomerDetail (sc);
> }

First, the Customer class has members which expose database data in an
object-oriented way. The class represents a "Customer." It is an object
which represents an entity, not an object which represents anything to do with a database. So, why would it make sense for it to expose a

DataReader,
especially since a DataReader must be closed, and the Connection with it?


it is just a psoude code , i generally use facade modeling ( using ms
enterprise library , data access app. block )

In fact, the UI layer shouldn't even be aware that it is working with a
database. It should be aware that it is working with a Customer object.
If
it needs the CompanyName, it gets it from the CompanyName property of the class. Etc. the UI's job is to present a "Customer" entity to a user in a user-friendly manner. And the business class's job is to present Customer data to the UI and other business objects in a programmer-friendly
manner.

So, first, the Customer class, in order to "mind its own business,"
should
only expose fields and properties pertaining to a Customer to client
classes.


I got the idea. if i need the all customers , i cant get it xx proterty , it
a dataset/datatable or something. Do I handle this situation and similar
situations using an private DataSet ? and return like

void button1_click()
{
structCustomers sc = new structCustomers(0);
sc.CustomerID = textbox1.text ;
Customers c = new Customers ();
c.GetCustomers();
dataset ds = c.dsCustomersAll;
}

But there's more. In that database function, what I see abstractly is a
function that executes a query or stored procedure, and returns a
SqlDataReader. Sounds like a potentially reusable function to me, with a little tweaking. How about a Data class with a static function like the
following?

public static SqlDataReader GetDataReader(SqlConnection conn,
SqlCommand command, string ProcedureName,
ParamArray params)
{
OpenConn(conn, command);
.....
return lcommand.ExecuteReader(ProcedureName, params);
}

Just a rough idea. You would have to flesh out the details yourself, of
course, including how to handle the ConnectionString, etc.


The idea is telling me that i have been on the right way already , i am
using facade pattern and ms entirprise library . I dont create commands, connection strings .
every class or only one connection is open for general use .
Now, the Customer class is the only class that will probably using this
Stored Procedure, so it will know the Procedure name and the parameters
needed. So, you have a method that populates the class from the Stored
Procedure, such as a Constructor method. Example:

public Customer(string CustomerID)
{
try
{
SqlCommand command;
SqlConnection conn;
SqlDataReader dr;
ParamArray params = ...;
dr = DataClass.GetDataReader(conn, command, "GetCustomer",

params);
...
_CustomerID = dr.GetString(dr.GetOrdinal("CustomerID"));
...
}
catch (Exception ex)
{...}
finally
{
dr.Close();
DataClass.CloseConn(conn, command);
}
}

Now the DataClass class encapsulates database functionality, and the
Customer class encapsulates all the process necessary to create a
Customer
with a simple API. Any UI class can simply create an instance of a

Customer
by passing the ID

That's the power of object-orientation!

--
HTH,

Kevin Spencer
Microsoft MVP
.Net Developer
Ambiguity has a certain quality to it.

Again thanks for the answer Kevin ,
have a nice day


Nov 17 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: David Winter | last post by:
I am looking for a "WYSIWYG" style, browser-based editor for (X)HTML content. It should (at least) run under Windows, preferably in Mozilla/Firefox, but IE would be OK, too. Now I know there are...
9
by: Hasan O. Zavalsiz | last post by:
Hi , i am trying to figure out which approach is better to use . let me explain the scenario. i am using the "Nortwind" database . in this database i have "Customers " table .The following is the...
5
by: G. Stewart | last post by:
The word "Business" in the term implies some sort of commercial aspects or connotations. But from what I can see, that is not necesserially the case at all? So what is the reasoning behind the...
4
by: GD | last post by:
I have a collection of asp:LinkButtons on a web form. Based on some reporting criteria, I will be "highlighting" some of these LinkButtons. I'd like the user to be able to mouseover the...
2
by: oliharvey | last post by:
Hi - (not really a C# question -...apologies) I seem to have gravitated towards a particlar design pattern - and would welcome your opinions as to it's sanity - thanks... The basic idea is...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.