Question about data layer

S

someone

Hi,
I have two C# beginer questions.
What's the best way to store an object (as an example, person) in the
database?
Option 1 - Having in the data layer an object "person" with a method
save(), and an object "person" in the business layer, so what I have to
do is to call the person.save() method in the business layer and this
method call the person.save() method in the data layer.
Or...
Option 2 - Having a DAL class with generics methods for all objects.
Those methods could be generateCommand() and executeCommand() and the
object "person" in the business layer has a save() method, when you call
person.save() in the business layer, it call to the methods
generateCommand() (to create the SQL sentence) and executeCommand() (to
execute the SQL sentence) and these methods saves the object "person" in
the database.

I saw it in both ways so I don't know what's best.

Another question:
If I have in the data layer two objects: Header and Detail (part of
invoice), and I have to load and invoice by invoice number: Who is in
charge for loading these two objects? or where do I have to do the load?
data layer? how?

In advance thanks a lot for any help.

Regards,
Marcelo.
 
P

Paul

LOL There will be a death on here today.

It is preference neither one is wrong and both can be validated by GRASP.

Option 1 for me tho.

Its time for home so I will try to post reasons tomorrow.

For your last question look up composition and aggregation, and don't forget
to enjoy. For an DAl external to Model lookup Pure Fabrication.
 
P

Paul

LOL There will be a death on here today.

It is preference neither one is wrong and both can be validated by GRASP.

Option 1 for me tho.

Its time for home so I will try to post reasons tomorrow.

For your last question look up composition and aggregation, and don't forget
to enjoy. For an DAl external to Model lookup Pure Fabrication.
 
S

someone

Paul escribió:
LOL There will be a death on here today.

Why are you so drastic? =)
I have been programming with VB5/6 for 10 years, I prefer option 1 (I'm
not sure how to implement it in C# yet), but I have seen several
examples using option 2, and actually I think that's wrong, because you
are adding SQL sentences in the business layer, If I change the
database, those SQL sentences could change, so I don't know why they use
that way...
That's why I'm asking it, actually I made this question in the spanish
Microsoft C# group a week ago but I haven't received any answer...

Thanks again.
Regards,
Marcelo.
 
S

someone

Paul escribió:
LOL There will be a death on here today.

Why are you so drastic? =)
I have been programming with VB5/6 for 10 years, I prefer option 1 (I'm
not sure how to implement it in C# yet), but I have seen several
examples using option 2, and actually I think that's wrong, because you
are adding SQL sentences in the business layer, If I change the
database, those SQL sentences could change, so I don't know why they use
that way...
That's why I'm asking it, actually I made this question in the spanish
Microsoft C# group a week ago but I haven't received any answer...

Thanks again.
Regards,
Marcelo.
 
S

sloan

As my blog points out. I prefer to have the DAL return
IDataReader(s)
DataSets (normally strong DataSets)
Scalars (Count(*) of a table would be an example)
voids (for updates, inserts, deletes when you don't need feedback)

The BAL will use the DAL....get the IDataReader.....consume it, then get rid
of it as soon as possible.

Because the DAL returns IDataReader(s), the DAL can be "switched" out to
another RDBMS with no effect on the BAL. IIRC, that was the point.

I also prefer Controller(or Manager) classes....in the BAL. Ex:
CustomerController.
The controller allows you to maintain the proper granularity on how much
data you serialize.

Ex: You have Customers, Orders, OrderDetails.
Sometimes you just want a list of Customers, and you don't want their Orders
(and OrderDetails).
Sometimes you want the whole shooting match, Customers,Orders and
OrderDetails.
Instead of having the business object make this decision (or passing "flags"
to it)...... the Controller controls granularity.

Also, if you serialize (WCF for instance) a bunch of Customer
objects.....you keep the objects very small.............
When you pass alot of data over the wire, you pay very close attention to
this.

.........................

If you're interested in multiple RDBMS support with the same BAL code, pay
attention to this blog entry specifically:
http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!176.entry


Start there and work your way up. LINQ throws some wrenches in the plans as
well. But save that for another day.
 
S

sloan

As my blog points out. I prefer to have the DAL return
IDataReader(s)
DataSets (normally strong DataSets)
Scalars (Count(*) of a table would be an example)
voids (for updates, inserts, deletes when you don't need feedback)

The BAL will use the DAL....get the IDataReader.....consume it, then get rid
of it as soon as possible.

Because the DAL returns IDataReader(s), the DAL can be "switched" out to
another RDBMS with no effect on the BAL. IIRC, that was the point.

I also prefer Controller(or Manager) classes....in the BAL. Ex:
CustomerController.
The controller allows you to maintain the proper granularity on how much
data you serialize.

Ex: You have Customers, Orders, OrderDetails.
Sometimes you just want a list of Customers, and you don't want their Orders
(and OrderDetails).
Sometimes you want the whole shooting match, Customers,Orders and
OrderDetails.
Instead of having the business object make this decision (or passing "flags"
to it)...... the Controller controls granularity.

Also, if you serialize (WCF for instance) a bunch of Customer
objects.....you keep the objects very small.............
When you pass alot of data over the wire, you pay very close attention to
this.

.........................

If you're interested in multiple RDBMS support with the same BAL code, pay
attention to this blog entry specifically:
http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!176.entry


Start there and work your way up. LINQ throws some wrenches in the plans as
well. But save that for another day.
 
S

someone

Thanks sloan! I have a lot to read with your blog...
I have to learn more about IDataReaders and Controllers...


Regards,
Marcelo.

sloan escribió:
 
S

someone

Thanks sloan! I have a lot to read with your blog...
I have to learn more about IDataReaders and Controllers...


Regards,
Marcelo.

sloan escribió:
 
P

Paul

It was tongue in cheek mate.

You do not need to put SQL code in option 2 just the ORM you can still
abstract to some extent by using SP's.

Option1 is IMHO the best but Option2 is probably viable if you have not
already created the framework of Option1 in your company and you are working
on a small project.
 
P

Paul

It was tongue in cheek mate.

You do not need to put SQL code in option 2 just the ORM you can still
abstract to some extent by using SP's.

Option1 is IMHO the best but Option2 is probably viable if you have not
already created the framework of Option1 in your company and you are working
on a small project.
 
P

Paul

Here is a ModelBase interface that alloows you to do that even over SOAP.
You may well ask why is this in the model? Well that is because I have
created these everywhere and IMHO this functionality is best here.


public interface IModelBase<TModelType>

{

int Id { get; set; }

DateTime DateArchived { get; set; }

TModelType UnderlyingValues { get; set; }

}

public interface IModelConcurrency

{

void PopulateUnderlyingValues();

void UndoChanges();

bool IsNew();

bool IsDirty(DataLoadingEnum dataLoadingLevel, int level);

bool IsArchive();

bool IsDirty(DataLoadingEnum dataLoadingLevel);

bool HasChanges

{

get;

set;

}

bool HasCompositeChanges

{

get;

set;

}

}



To get you going these are refection based but you can create an abstract
class and make each method virtual to allow you to ovveride in each to
remove the perfromance hit of reflection. but these reletive based methods
are good for prototypes. You DAL calls populate after it has populated the
object. Whan you call Save you identify if isNew, isDirty, Isarchive/delete.
I will not give you all the code because you need to understand and probably
do it your own way Data Access is personal and each has their opinion, but
hopefully it gives you an idea of how the model can support the DAL, and
still be useable over SOAP, rather than methods in properties which in my
opinion do not work as well but thats just my opinion and any way that work
well is fine.

public abstract class ModelBase<TModelType> : IModelBase<TModelType>,
IModelConcurrency where TModelType : ModelBase<TModelType>, new()

{

public virtual void PopulateUnderlyingValues()

{

Type type = typeof(TModelType);

//Get a list of public properties

if (UnderlyingValues == null)

UnderlyingValues = new TModelType();

PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance |
BindingFlags.Public);

//for each property populate the corresponding underlying value from the
object property

foreach (PropertyInfo property in properties)

{

if (property.CanWrite && property.Name != "UnderlyingValues")

{

property.SetValue(UnderlyingValues, property.GetValue(this, null), null);

}

}

}

public bool IsNew()

{

if (this.UnderlyingValues == null)

return true;

else

return false;

}

}
 
P

Paul

Here is a ModelBase interface that alloows you to do that even over SOAP.
You may well ask why is this in the model? Well that is because I have
created these everywhere and IMHO this functionality is best here.


public interface IModelBase<TModelType>

{

int Id { get; set; }

DateTime DateArchived { get; set; }

TModelType UnderlyingValues { get; set; }

}

public interface IModelConcurrency

{

void PopulateUnderlyingValues();

void UndoChanges();

bool IsNew();

bool IsDirty(DataLoadingEnum dataLoadingLevel, int level);

bool IsArchive();

bool IsDirty(DataLoadingEnum dataLoadingLevel);

bool HasChanges

{

get;

set;

}

bool HasCompositeChanges

{

get;

set;

}

}



To get you going these are refection based but you can create an abstract
class and make each method virtual to allow you to ovveride in each to
remove the perfromance hit of reflection. but these reletive based methods
are good for prototypes. You DAL calls populate after it has populated the
object. Whan you call Save you identify if isNew, isDirty, Isarchive/delete.
I will not give you all the code because you need to understand and probably
do it your own way Data Access is personal and each has their opinion, but
hopefully it gives you an idea of how the model can support the DAL, and
still be useable over SOAP, rather than methods in properties which in my
opinion do not work as well but thats just my opinion and any way that work
well is fine.

public abstract class ModelBase<TModelType> : IModelBase<TModelType>,
IModelConcurrency where TModelType : ModelBase<TModelType>, new()

{

public virtual void PopulateUnderlyingValues()

{

Type type = typeof(TModelType);

//Get a list of public properties

if (UnderlyingValues == null)

UnderlyingValues = new TModelType();

PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance |
BindingFlags.Public);

//for each property populate the corresponding underlying value from the
object property

foreach (PropertyInfo property in properties)

{

if (property.CanWrite && property.Name != "UnderlyingValues")

{

property.SetValue(UnderlyingValues, property.GetValue(this, null), null);

}

}

}

public bool IsNew()

{

if (this.UnderlyingValues == null)

return true;

else

return false;

}

}
 
P

Paul

I can see where you are going with this but the concept of a BAL is a bit
missleading. The DAL in computer concept is described as the application
than returns a reference to an object in OO terms rather than a set of rows
or fields, allowing a high level of abstraction from the db. To return a
IDateReader here is misleading IMHO.

Personally I would rename your BAL as the DAL and rename your DAL as a
DataProvider/DataProviderFacade.

What your DAL (Data Provider) is in essence doing is acting as a
Facade/Strategy over potentially numerous Database Provider Types (SQL
Server, Oracle, My Sql etc etc) not doing the ORM stuff and returning a
model object.

Its a great model and one that I only thought a nutter like me used. Like I
said my personal preference would be to rename your layers, but I still like
it more than any other options I've ever heard developers mention on the
net.

Someone from microsoft, I think you ignored my previous comments cause you
thought I was been awkward but I was not. You should still try to understand
the GRASP principles in Larmans book and read up on Composites and
aggregation these will aid you significatly if you are creating a Data
Access Framework for your company. These are not gospel and even Larman
says...PICK YOUR BATTLES.. and this is the hardest point to learn of all,
and im still trying...;-)

Another thing to watch out for is because you have moved all functionality
(well maybe) out of model objects it can also be difficult to do things like
Lazy loading without further calls into the layers, so you will need the
notion of layers and to what extent your BLL needs to load Aggregated
Composites, not deep enough and you will not populate your object correctly
too deep and you grind the app to a halt, so try to make it flexible so you
can load layers only that are needed in the ui.

e.g.

Person employee
string name
Address homeAddress
Person Manager
string name
Address homeAddress
Person Manager
string name
Address homeAddress
Person Manager
string name
Address homeAddress
Person Manager
etc...
etc....

How much information do you need? Load only to that level.
 

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