solution architecture regarding typed datasets

B

BillE

I have a VS 2008 solution containing a number of projects, including windows
forms, web forms, business classes, and a data access layer.

I have been diligent about separating UI from business rules and objects,
and the data access layer.

I'm not sure how this should work with typed datasets.

To populate a typed dataset, to be used as a datasource for a datagridview,
for example, all three layers have to create an instance of the typed
dataset. The business class needs to get an instance of the typed dataset
from the data access layer, and pass it to the UI layer.

It seems inappropriate to me that a separate function in the data access
layer should be necessary for each different typed dataset which is required
in the solution. A separate function already exists in the business
objects layer for each type of dataset required.

I don't want to use classes as data sources instead of typed datasets,
because datagridview controls aren't sortable when classes are used as the
datasource, unfortunately.

Consequently, I am embarassed to admit that I have been using generic
datasets. I assume I am lacking an important piece of the puzzle, so I
would appreciate it if someone could help me with this.
 
S

sloan

Datasets (in your case) act as the layer-GLUE to allow the different layers
to work together.

My preference is to actually put them in their own assembly.........and each
layer (assembly) references this "glue" assembly.


/Presentation/
/BusinessLogic/
/DataLayer/
/Data.DataSets/


Presentation references BusinessLogic and Data.DataSets.
BusinessLogic references DataLayer and Data.DataSets
DataLayer references Data.DataSets

PresentationLayer does NOT (ever) reference DataLayer.


You can go here:
http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!139.entry

Find the MS article I reference at the bottom. ("bird's eye view") is what
I call it I think.

Bookmark the MS article. Read it. Read it again. Reread it in 2 months.

They give the options......



Here is the place to find in the MS article:
Deploying Business Entities
Deploying Business Entities implemented as typed DataSets. The typed DataSet
class must be __________________________<< you can read about it at the MS
article.
 
B

BillE

Thanks, I will read this.

Do you maintain a separate function in your data layer for each typed
dataset?
 
S

sloan

Follow my blog link, and you can download a working example.

But yes.........I have methods in the DataLayer which return instances of
the typed DataSet.

Here is a small sample:

public EmployeeDS FindAllEmployeesAndDepartments ( )
{

EmployeeDS returnDS = new EmployeeDS();

//code here to LoadDataSet and fill the returnDS;...........//with all
employees and all departments

return returnDS;

}

public EmployeeDS FindSingleEmployeesAndDepartments ( int employeeID )
{

EmployeeDS returnDS = new EmployeeDS();

//code here to LoadDataSet and fill the returnDS;.......//with 1
employee and all depts

return returnDS;

}



I would also recommend the DAAB 2.0 or better yet the EnterpriseLibrary.Data
framework.

Its keeps your DAL code very "lean and clean".

Here is a sample:
Your focus is on the usp (user stored procedure name) and the parameters.
You don't get bogged down in SqlConnection and SqlCommand objects.

See how clean the example is below (EnterpriseLibrary.Data 3.1 code)



public EmployeeDS FindSingleEmployeeAndDepartmentsBySSN(string
employeeSSN)
{

EmployeeDS returnDs = new EmployeeDS();
Database db = null;

try
{
db = this.GetDatabase(); //encapsulated call
DbCommand dbc =
db.GetStoredProcCommand("dbo.EmployeeGetSingleBySSN");
db.AddInParameter(dbc, "@SSN", DbType.String, employeeSSN);
db.LoadDataSet(dbc, returnDs, new string[] {
returnDs.Employee.TableName, returnDs.Department.TableName });
}
finally
{
}

return returnDs;

}






public IDataReader CustomersGetSingleWithOrdersReader(string
customerId)
{

IDataReader returnReader = null;
try
{
Database db = this.GetDatabase();
DbCommand dbc =
db.GetStoredProcCommand(PROC_CUSTOMER_GET_SINGLE_BY_ID); // This is a CONST
from earlier in the class

//Again another CONST from above...
db.AddInParameter(dbc, PARAMETER_CUSTOMER_ID,
System.Data.DbType.String, customerId);


returnReader = db.ExecuteReader(dbc);
return returnReader;
}
finally
{
}
}
 
P

Paul

Ok...Where to start...Oh yeah...Never use datasets, typed or not, unless for
prototyping.

Why would you want to bring all Employees back for editing (maybe 10 maybe
100000000000)? I presume you are editing or why use datasets?

Databases are good at locating and sorting records let the db do the work
for you. What you prolly need to do however is page the records which again
you do not need datasets for.

And...even if you want to sort all records... see this o sorting arrays/lists

http://groups.google.co.uk/group/mi...9a64e77097/2b7528c689f9ef84?#2b7528c689f9ef84


sloan said:
Follow my blog link, and you can download a working example.

But yes.........I have methods in the DataLayer which return instances of
the typed DataSet.

Here is a small sample:

public EmployeeDS FindAllEmployeesAndDepartments ( )
{

EmployeeDS returnDS = new EmployeeDS();

//code here to LoadDataSet and fill the returnDS;...........//with all
employees and all departments

return returnDS;

}

public EmployeeDS FindSingleEmployeesAndDepartments ( int employeeID )
{

EmployeeDS returnDS = new EmployeeDS();

//code here to LoadDataSet and fill the returnDS;.......//with 1
employee and all depts

return returnDS;

}



I would also recommend the DAAB 2.0 or better yet the EnterpriseLibrary.Data
framework.

Its keeps your DAL code very "lean and clean".

Here is a sample:
Your focus is on the usp (user stored procedure name) and the parameters.
You don't get bogged down in SqlConnection and SqlCommand objects.

See how clean the example is below (EnterpriseLibrary.Data 3.1 code)



public EmployeeDS FindSingleEmployeeAndDepartmentsBySSN(string
employeeSSN)
{

EmployeeDS returnDs = new EmployeeDS();
Database db = null;

try
{
db = this.GetDatabase(); //encapsulated call
DbCommand dbc =
db.GetStoredProcCommand("dbo.EmployeeGetSingleBySSN");
db.AddInParameter(dbc, "@SSN", DbType.String, employeeSSN);
db.LoadDataSet(dbc, returnDs, new string[] {
returnDs.Employee.TableName, returnDs.Department.TableName });
}
finally
{
}

return returnDs;

}






public IDataReader CustomersGetSingleWithOrdersReader(string
customerId)
{

IDataReader returnReader = null;
try
{
Database db = this.GetDatabase();
DbCommand dbc =
db.GetStoredProcCommand(PROC_CUSTOMER_GET_SINGLE_BY_ID); // This is a CONST
from earlier in the class

//Again another CONST from above...
db.AddInParameter(dbc, PARAMETER_CUSTOMER_ID,
System.Data.DbType.String, customerId);


returnReader = db.ExecuteReader(dbc);
return returnReader;
}
finally
{
}
}




BillE said:
Thanks, I will read this.

Do you maintain a separate function in your data layer for each typed
dataset?
 
S

sloan

"Employee" is just a sample Entity. It could have been "State" (as in , the
USA has 50 of them). It could have been "Product". It was sample code to
convey an idea, not just a single implementation.

Databases are good for CRUD operations.

Sorting? Debatable. On highly scaled systems, I've seen the middle tier
being used for the the sorting. To take some load off of the db servers.
Sometimes the ORDER BY statement in the database might to be high a penalty.
Thus it can be offloaded to the middle tier. Sometimes...that means "not
always" or "probably not the majority of time", but rather sometimes.

If you followed my blog, I actually am FOR custom objects and custom object
collections.

However, there are times when DataSets make sense. In my job and in the
last 5 years, I seldom make use of DataSets.
But I don't throw out blanket statements like "Never use datasets".
Sometimes they make sense........and not only on prototyping scenarios.


There are pros and cons. Instead of blanket statements....this type of work
where the pros are cons are carefully laid out and discussed seems the wiser
approch to which way to go:
http://msdn.microsoft.com/en-us/library/ms978496.aspx


''Why would you want to bring all Employees back for editing''

You assume "editing". Why do I have to edit what I bring back? Maybe I
have a list report ... and the list report is called "All Employees Report".
If I had to create a report that needed all employees, guess what? I would
have to retrieve all employees from the database.


In fact, reporting is a good reason to use (strong) datasets. You don't
want to create a business object library for some reports....which are very
subject to change.
This is the one area where I do use datasets. And in fact, when I am asked
to use Crystal Reports (for example), using the "PUSH" method and sending it
a dataset is a much more maintainable report system ... .rather than the
Crystal Reports PULL method. Why? Because you can see the data in the
dataset before it goes off to Crystal Reports.......and thus Crystal Reports
becomes a true(er) presentation layer.
And if you ever wanted to drop Crystal in favor of (let's say Active
Reports) you don't screw yourself. Because all of your dataset creation
remains in tact........instead of the hours and hours of rewrite you would
have to do with the PULL method.





Paul said:
Ok...Where to start...Oh yeah...Never use datasets, typed or not, unless
for
prototyping.

Why would you want to bring all Employees back for editing (maybe 10 maybe
100000000000)? I presume you are editing or why use datasets?

Databases are good at locating and sorting records let the db do the work
for you. What you prolly need to do however is page the records which
again
you do not need datasets for.

And...even if you want to sort all records... see this o sorting
arrays/lists

http://groups.google.co.uk/group/mi...9a64e77097/2b7528c689f9ef84?#2b7528c689f9ef84


sloan said:
Follow my blog link, and you can download a working example.

But yes.........I have methods in the DataLayer which return instances of
the typed DataSet.

Here is a small sample:

public EmployeeDS FindAllEmployeesAndDepartments ( )
{

EmployeeDS returnDS = new EmployeeDS();

//code here to LoadDataSet and fill the returnDS;...........//with
all
employees and all departments

return returnDS;

}

public EmployeeDS FindSingleEmployeesAndDepartments ( int employeeID )
{

EmployeeDS returnDS = new EmployeeDS();

//code here to LoadDataSet and fill the returnDS;.......//with 1
employee and all depts

return returnDS;

}



I would also recommend the DAAB 2.0 or better yet the
EnterpriseLibrary.Data
framework.

Its keeps your DAL code very "lean and clean".

Here is a sample:
Your focus is on the usp (user stored procedure name) and the parameters.
You don't get bogged down in SqlConnection and SqlCommand objects.

See how clean the example is below (EnterpriseLibrary.Data 3.1 code)



public EmployeeDS FindSingleEmployeeAndDepartmentsBySSN(string
employeeSSN)
{

EmployeeDS returnDs = new EmployeeDS();
Database db = null;

try
{
db = this.GetDatabase(); //encapsulated call
DbCommand dbc =
db.GetStoredProcCommand("dbo.EmployeeGetSingleBySSN");
db.AddInParameter(dbc, "@SSN", DbType.String,
employeeSSN);
db.LoadDataSet(dbc, returnDs, new string[] {
returnDs.Employee.TableName, returnDs.Department.TableName });
}
finally
{
}

return returnDs;

}






public IDataReader CustomersGetSingleWithOrdersReader(string
customerId)
{

IDataReader returnReader = null;
try
{
Database db = this.GetDatabase();
DbCommand dbc =
db.GetStoredProcCommand(PROC_CUSTOMER_GET_SINGLE_BY_ID); // This is a
CONST
from earlier in the class

//Again another CONST from above...
db.AddInParameter(dbc, PARAMETER_CUSTOMER_ID,
System.Data.DbType.String, customerId);


returnReader = db.ExecuteReader(dbc);
return returnReader;
}
finally
{
}
}




BillE said:
Thanks, I will read this.

Do you maintain a separate function in your data layer for each typed
dataset?


Datasets (in your case) act as the layer-GLUE to allow the different
layers to work together.

My preference is to actually put them in their own
assembly.........and
each layer (assembly) references this "glue" assembly.


/Presentation/
/BusinessLogic/
/DataLayer/
/Data.DataSets/


Presentation references BusinessLogic and Data.DataSets.
BusinessLogic references DataLayer and Data.DataSets
DataLayer references Data.DataSets

PresentationLayer does NOT (ever) reference DataLayer.


You can go here:
http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!139.entry

Find the MS article I reference at the bottom. ("bird's eye view") is
what I call it I think.

Bookmark the MS article. Read it. Read it again. Reread it in 2
months.

They give the options......



Here is the place to find in the MS article:
Deploying Business Entities
Deploying Business Entities implemented as typed DataSets. The typed
DataSet class must be __________________________<< you can read about
it
at the MS article.



I have a VS 2008 solution containing a number of projects, including
windows forms, web forms, business classes, and a data access layer.

I have been diligent about separating UI from business rules and
objects, and the data access layer.

I'm not sure how this should work with typed datasets.

To populate a typed dataset, to be used as a datasource for a
datagridview, for example, all three layers have to create an
instance
of the typed dataset. The business class needs to get an instance of
the typed dataset from the data access layer, and pass it to the UI
layer.

It seems inappropriate to me that a separate function in the data
access
layer should be necessary for each different typed dataset which is
required in the solution. A separate function already exists in the
business objects layer for each type of dataset required.

I don't want to use classes as data sources instead of typed
datasets,
because datagridview controls aren't sortable when classes are used
as
the datasource, unfortunately.

Consequently, I am embarassed to admit that I have been using generic
datasets. I assume I am lacking an important piece of the puzzle, so
I
would appreciate it if someone could help me with this.
 
P

Paul

Interesting.

Firstly the question was related to binding a dataset to a gridview so
reporting was moot. But as you mentioned it I will pick that up in a tick. So
would you return all rows to a datagrid using a dataset and use the dataset
to do sorting in the front end??

Secondly. If SQL Server is having performance problems processing a Query,
do you really think scaling this to your Middle tier is going to help. Your
code will never out perform SQL Server in processing a query or sorting a
query. Yes doing some sort of caching may help, but think of the memory
issues not to mention data consistency issues you have to solve yourself.
Eventually you have to scale hardware and ask yourself where is this best
done. My opinion scale what is best at doing the job, don't tie up all the
complex BLL because you are attempting to do something the Data server is
better at doing. You have coded you way out of options. An extra SQL box
means also an extra BLL box in your scenario, I say this because with all the
extra data consistency work you have to do I don't think you saved much work
for the DB Server in the long term.

Finally running reports through your BLL and passing Datasets to your
reporting tool of choice. There is a reason why in OO Principles Reporting
does not sit in with Use Cases. Come on performance is one reason not to do
this, databases can cause enough issues in reporting senario's which is why
companies spend small fortunes on Datawarehousing. If you tell me you reuse
you BLL, fair enough on small projects but comeone that means everytime sally
in accounts wants a new report requiring changes you have to change the DAL
and re-realease reporting/app to all or suffer version differences. What
happens if a chnage to a DS messes up a dataset used by your BLL/non
reporting. You cannot tell me this is manageable on all but the smallest
projects.

Oh and Finally finally. Datasets over SOAP or any boundry how much heavier,
not to mention forget non .NET apps using them...



sloan said:
"Employee" is just a sample Entity. It could have been "State" (as in , the
USA has 50 of them). It could have been "Product". It was sample code to
convey an idea, not just a single implementation.

Databases are good for CRUD operations.

Sorting? Debatable. On highly scaled systems, I've seen the middle tier
being used for the the sorting. To take some load off of the db servers.
Sometimes the ORDER BY statement in the database might to be high a penalty.
Thus it can be offloaded to the middle tier. Sometimes...that means "not
always" or "probably not the majority of time", but rather sometimes.

If you followed my blog, I actually am FOR custom objects and custom object
collections.

However, there are times when DataSets make sense. In my job and in the
last 5 years, I seldom make use of DataSets.
But I don't throw out blanket statements like "Never use datasets".
Sometimes they make sense........and not only on prototyping scenarios.


There are pros and cons. Instead of blanket statements....this type of work
where the pros are cons are carefully laid out and discussed seems the wiser
approch to which way to go:
http://msdn.microsoft.com/en-us/library/ms978496.aspx


''Why would you want to bring all Employees back for editing''

You assume "editing". Why do I have to edit what I bring back? Maybe I
have a list report ... and the list report is called "All Employees Report".
If I had to create a report that needed all employees, guess what? I would
have to retrieve all employees from the database.


In fact, reporting is a good reason to use (strong) datasets. You don't
want to create a business object library for some reports....which are very
subject to change.
This is the one area where I do use datasets. And in fact, when I am asked
to use Crystal Reports (for example), using the "PUSH" method and sending it
a dataset is a much more maintainable report system ... .rather than the
Crystal Reports PULL method. Why? Because you can see the data in the
dataset before it goes off to Crystal Reports.......and thus Crystal Reports
becomes a true(er) presentation layer.
And if you ever wanted to drop Crystal in favor of (let's say Active
Reports) you don't screw yourself. Because all of your dataset creation
remains in tact........instead of the hours and hours of rewrite you would
have to do with the PULL method.





Paul said:
Ok...Where to start...Oh yeah...Never use datasets, typed or not, unless
for
prototyping.

Why would you want to bring all Employees back for editing (maybe 10 maybe
100000000000)? I presume you are editing or why use datasets?

Databases are good at locating and sorting records let the db do the work
for you. What you prolly need to do however is page the records which
again
you do not need datasets for.

And...even if you want to sort all records... see this o sorting
arrays/lists

http://groups.google.co.uk/group/mi...9a64e77097/2b7528c689f9ef84?#2b7528c689f9ef84


sloan said:
Follow my blog link, and you can download a working example.

But yes.........I have methods in the DataLayer which return instances of
the typed DataSet.

Here is a small sample:

public EmployeeDS FindAllEmployeesAndDepartments ( )
{

EmployeeDS returnDS = new EmployeeDS();

//code here to LoadDataSet and fill the returnDS;...........//with
all
employees and all departments

return returnDS;

}

public EmployeeDS FindSingleEmployeesAndDepartments ( int employeeID )
{

EmployeeDS returnDS = new EmployeeDS();

//code here to LoadDataSet and fill the returnDS;.......//with 1
employee and all depts

return returnDS;

}



I would also recommend the DAAB 2.0 or better yet the
EnterpriseLibrary.Data
framework.

Its keeps your DAL code very "lean and clean".

Here is a sample:
Your focus is on the usp (user stored procedure name) and the parameters.
You don't get bogged down in SqlConnection and SqlCommand objects.

See how clean the example is below (EnterpriseLibrary.Data 3.1 code)



public EmployeeDS FindSingleEmployeeAndDepartmentsBySSN(string
employeeSSN)
{

EmployeeDS returnDs = new EmployeeDS();
Database db = null;

try
{
db = this.GetDatabase(); //encapsulated call
DbCommand dbc =
db.GetStoredProcCommand("dbo.EmployeeGetSingleBySSN");
db.AddInParameter(dbc, "@SSN", DbType.String,
employeeSSN);
db.LoadDataSet(dbc, returnDs, new string[] {
returnDs.Employee.TableName, returnDs.Department.TableName });
}
finally
{
}

return returnDs;

}






public IDataReader CustomersGetSingleWithOrdersReader(string
customerId)
{

IDataReader returnReader = null;
try
{
Database db = this.GetDatabase();
DbCommand dbc =
db.GetStoredProcCommand(PROC_CUSTOMER_GET_SINGLE_BY_ID); // This is a
CONST
from earlier in the class

//Again another CONST from above...
db.AddInParameter(dbc, PARAMETER_CUSTOMER_ID,
System.Data.DbType.String, customerId);


returnReader = db.ExecuteReader(dbc);
return returnReader;
}
finally
{
}
}




Thanks, I will read this.

Do you maintain a separate function in your data layer for each typed
dataset?


Datasets (in your case) act as the layer-GLUE to allow the different
layers to work together.

My preference is to actually put them in their own
assembly.........and
each layer (assembly) references this "glue" assembly.


/Presentation/
/BusinessLogic/
/DataLayer/
/Data.DataSets/


Presentation references BusinessLogic and Data.DataSets.
BusinessLogic references DataLayer and Data.DataSets
DataLayer references Data.DataSets

PresentationLayer does NOT (ever) reference DataLayer.


You can go here:
http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!139.entry

Find the MS article I reference at the bottom. ("bird's eye view") is
what I call it I think.

Bookmark the MS article. Read it. Read it again. Reread it in 2
months.

They give the options......



Here is the place to find in the MS article:
Deploying Business Entities
Deploying Business Entities implemented as typed DataSets. The typed
DataSet class must be __________________________<< you can read about
it
at the MS article.



I have a VS 2008 solution containing a number of projects, including
windows forms, web forms, business classes, and a data access layer.

I have been diligent about separating UI from business rules and
objects, and the data access layer.

I'm not sure how this should work with typed datasets.

To populate a typed dataset, to be used as a datasource for a
datagridview, for example, all three layers have to create an
instance
of the typed dataset. The business class needs to get an instance of
the typed dataset from the data access layer, and pass it to the UI
layer.

It seems inappropriate to me that a separate function in the data
access
layer should be necessary for each different typed dataset which is
required in the solution. A separate function already exists in the
business objects layer for each type of dataset required.

I don't want to use classes as data sources instead of typed
datasets,
because datagridview controls aren't sortable when classes are used
as
the datasource, unfortunately.

Consequently, I am embarassed to admit that I have been using generic
datasets. I assume I am lacking an important piece of the puzzle, so
I
would appreciate it if someone could help me with this.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top