I am learning entity classes and for that I made a small application that insert simple data into database. The code below might be totally incorrect so please help me make it better so I have better idea of patterns.
asp.net page code:
private void Button1_Click(object sender, System.EventArgs e)
{
Person person = new Person();
person.Name = "azam";
person.DateCreated = DateTime.Now;
person.Password = "MyPassword";
if(person.AddUser(person) > 0)
Response.Write("New user added");
else
Response.Write("Not added");
}
DBPerson.cs file:
public class Person
{
private int _personId = 0;
private string _name = null;
private DateTime _dateCreated;
private string _password = null;
public int PersonID
{
get
{
return _personId;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public DateTime DateCreated
{
get
{
return _dateCreated;
}
set
{
_dateCreated = value;
}
}
public string Password
{
get
{
return _password;
}
set
{
_password = value;
}
}
// Methods defination
public int AddUser(Person person)
{
Database db = DatabaseFactory.CreateDatabase();
DBCommandWrapper insertCommandWrapper = db.GetStoredProcCommandWrapper("sp_InsertPerson");
if(person.AddUser(person) > 0)
Response.Write("New user added");
else Response.Write("Not added");
////
person.AddUser(person) is broken as hell.. even is
person.Save() is a better solution.. the best one would be working with Managers than can save any type of objects for you. I think you read before
in this forms about the term O/R-mappers.. and maybe you're interested to make your code just better and cut the ugly SQL (even if it's a call for your stored procedure...) from your code.
Note that if you program all your classes this way. you need to include in SQL in EVERY class with CRUD functionality. that can be a lot of unnecessary code that you can avoid. if you do this, just take a look at your
code; it's repetitive code everywhere, and just not easy to maintain. try it out and change the name of 3/4 columns in the DB, and you will need to change this in more places in your code...
by using a proper O/R-mapper, you can centralize the mapping between your object-schema and the DB-schema... and the code will be easier to maintain. Not just that, all this SQL you write right now will a unnecessary and there will be no need to write it yourself.
It saves time, and your code will be just cleaner. just read the other threads about it...
Bluemagics Weblog: "I'll always make your dark sky blue!"
You are definitely on the right track here - this is a HUGE improvement over your most recent posts. I have a few suggestions and I am sure that Thona will have a few as well [;)]
I recently learned (thanks to this forum) that static methods are not a good way to do CRUD. Use manager classes to handle CRUD and optimally GENERIC manager classes, e.g.
private void Button1_Click(object sender, System.EventArgs e) { Person person = new Person(); person.Name = "azam"; person.DateCreated = DateTime.Now; person.Password = "MyPassword";
// ONE WAY // -------------- // This class does the CRUD PersonManager mgr = new PersonManager(); mgr.Save(person);
// BETTER WAY (basis of OR-Mapper stuff) // ------------------ ObjectManager mgr = new ObjectManager();
// Save the person mgr.Save(person);
// Save another object of a different type (generic) mgr.Save(otherObject);
// Commit the transaction mgr.Commit(); }
Now a lot of people ask HOW can this generic stuff work. I'm not going to delve into how the OR-mapper vendors do this stuff, but I will give an example of some generic code using the factory pattern. (excuse my C#)
class ObjectManager { public void Save(Object obj) { IObjectManager mgr = ManagerFactory.Create(obj.GetType()); mgr.Save(obj)
}
class ManagerFactory { static IObjectManager Create(Type t) { // either hard code managers based upon type (BAD WAY) // or use a config file and reflection to dynamically create instances if (t.Equals(typeof(Employee)) {
return new EmployeeManager();
}
}
}
class EmployeeManager : IObjectManager {
public void IObjectManager.Save(Object obj) { // CRUD GOES HERE
}
...
}
}
You will still do a lot of CRUD this way but its more organized. Let the flaming begin [:|]
>>>>change the name of 3/4 columns in the DB, and you will need to change this in more places in your code...
I don't understand that why anyone would like to change the name of the columns in the database. This is a very very huge change that will reflect throughout the application.
To EVO:
Thanks a lot EVO. I will look into the code you gave me. Also is the code below being generated by the OR/MAPPERS or you have to type it manually. I don't have any access to OR/MAPPERS and I have never used them yet but would like to.
class ObjectManager { public void Save(Object obj) { IObjectManager mgr = ManagerFactory.Create(obj.GetType()); mgr.Save(obj)
}
class ManagerFactory { static IObjectManager Create(Type t) { // either hard code managers based upon type (BAD WAY) // or use a config file and reflection to dynamically create instances if (t.Equals(typeof(Employee)) {
return new EmployeeManager();
}
}
}
class EmployeeManager : IObjectManager {
public void IObjectManager.Save(Object obj) { // CRUD GOES HERE
My 2 cents regarding the whole "Column change" argument is this:
ALMOST any database schema change is going to be reflected in every layer of the application. For example, adding a column, removing a column, etc. 99% of columns map to business attributes so if you add a column, for example "SSN", you are going to be adding
a new property in your BLL, and you are going to be adding a new label or textbox in your UI. It's that simple.
The only changes which MAY not be reflected in every layer are simple changes like adding a default value to a column, tuning your database with indexes, and the like.
How often do people rename columns? NOT VERY and when they do rename them, it's probably because they mispelled a word or violated some sort of design guideline which means they are going to be re-architecting more than just the DAL.
----
I digress. Anyways, regarding code generation - yes, you can use a code generator to make your Manager classes. As Thona pointed out in a previous post, code gens aren't the be-all end-all and you don't get a lot of the features that come with a good OR-Mapper.
Try to keep the following in mind however - if you have a good separation of responsibility through proper layering, you can get away with using the Manager system as demonstrated above and don't have to worry about performance until it becomes an issue.
Using a generic DAL (ObjectManager) allows you to write the bare minimal and later go back and tune without rewriting your UI or BLL layers.
Don't assume performance is an issue until it really is an issue. You don't need a OR-Mapper just because everyone says you should use one. A well designed application will be easy to maintain and isolate changes. That's the real goal. OR-Mappers just facilitate
this process.
Also is the code below being generated by the OR/MAPPERS or you have to type it manually.
Wrong. An O/R mapper would not generate the above code. The above code is repetitive, and as such would be handled ina generic way. There is no need to have more than one type of ObjectManager.
I don't have any access to OR/MAPPERS
Wrong. Unless you have someone type in your texts posting on this forums indicates access to the internet. All O/R mapper vendors have websites. Plus there are open source projects. Whether you choose to ignore them or not, you DO have access to them.
Hmmm... books, good question. Let's see, I got the Object Primer and Building Object Applications that Work by Scott Ambler, the Object Primer is very basic, but BOATW is a pretty decent read for overall OOP.
Most of the MS books are going to advocate a Dataset oriented approach and should be avoided.
Expert One-On-One Business Objects by Lhotka is OK for its information on remoting, but a lot of the stuff regarding OOP is flawed - e.g. putting CRUD directly in the object.
I haven't really found a good book on architecture as far as .NET goes, but if you do a search for books/articles on Java architecture, you are going to find a lot of things. Java has been around for a lot longer and naturally has a lot of stuff regarding
architecture available. The two platforms are similar enough that I'm sure you can make the connections.
I would suggest that you take a look at DotNetNuke and see how persisting and loading objects is handeled in there. That will get you on the right track, and once you understand how it works. If you want to do DDD I would suggest looking at NHibernate open
source O/R Mapper.
Here is example of how it is done in DNN ( in my classes I user Persist method that knows if data needs to be inserted or updated)
DocumentInfo
Public
Property ItemId() As Integer
Get
Return _ItemId
End Get
Set(ByVal Value
As Integer)
_ItemId = Value
End Set
End Property
DocumentController
Public
Sub AddDocument(ByVal objDocument
As DocumentInfo)
Public
MustOverride Function AddDocument(ByVal ModuleId
As Integer,
ByVal Title As String,
ByVal URL As
String, ByVal UserName
As String, ByVal Category
As String)
As Integer
SqlDataProvider
Public
Overrides Function AddDocument(ByVal ModuleId
As Integer,
ByVal Title As
String, ByVal URL
As String,
ByVal UserName As
String, ByVal Category
As String)
As Integer
azamsharp
All-Star
24614 Points
4612 Posts
Is this the right way to insert new item
May 23, 2005 03:13 AM|LINK
asp.net page code:
private void Button1_Click(object sender, System.EventArgs e)
{
Person person = new Person();
person.Name = "azam";
person.DateCreated = DateTime.Now;
person.Password = "MyPassword";
if(person.AddUser(person) > 0)
Response.Write("New user added");
else
Response.Write("Not added");
}
DBPerson.cs file:
public class Person
{
private int _personId = 0;
private string _name = null;
private DateTime _dateCreated;
private string _password = null;
public int PersonID
{
get
{
return _personId;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public DateTime DateCreated
{
get
{
return _dateCreated;
}
set
{
_dateCreated = value;
}
}
public string Password
{
get
{
return _password;
}
set
{
_password = value;
}
}
// Methods defination
public int AddUser(Person person)
{
Database db = DatabaseFactory.CreateDatabase();
DBCommandWrapper insertCommandWrapper = db.GetStoredProcCommandWrapper("sp_InsertPerson");
insertCommandWrapper.AddInParameter("@Email",DbType.String,person.Name);
insertCommandWrapper.AddInParameter("@DateCreated",DbType.DateTime,person.DateCreated);
insertCommandWrapper.AddInParameter("@Password",DbType.String,person.Password);
try
{
db.ExecuteNonQuery(insertCommandWrapper);
}
catch(Exception ex)
{
string exception = ex.Message;
}
return insertCommandWrapper.RowsAffected;
}
}
Thanks,
HighOnCoding
Bluemagics
Participant
1955 Points
391 Posts
Re: Is this the right way to insert new item
May 23, 2005 10:53 AM|LINK
Response.Write("New user added");
else
Response.Write("Not added");
////
person.AddUser(person) is broken as hell.. even is person.Save() is a better solution.. the best one would be working with Managers than can save any type of objects for you. I think you read before in this forms about the term O/R-mappers.. and maybe you're interested to make your code just better and cut the ugly SQL (even if it's a call for your stored procedure...) from your code.
Note that if you program all your classes this way. you need to include in SQL in EVERY class with CRUD functionality. that can be a lot of unnecessary code that you can avoid. if you do this, just take a look at your code; it's repetitive code everywhere, and just not easy to maintain. try it out and change the name of 3/4 columns in the DB, and you will need to change this in more places in your code...
by using a proper O/R-mapper, you can centralize the mapping between your object-schema and the DB-schema... and the code will be easier to maintain. Not just that, all this SQL you write right now will a unnecessary and there will be no need to write it yourself. It saves time, and your code will be just cleaner. just read the other threads about it...
evo
Participant
840 Points
168 Posts
Re: Is this the right way to insert new item
May 23, 2005 12:19 PM|LINK
Azam,
You are definitely on the right track here - this is a HUGE improvement over your most recent posts. I have a few suggestions and I am sure that Thona will have a few as well [;)]
I recently learned (thanks to this forum) that static methods are not a good way to do CRUD. Use manager classes to handle CRUD and optimally GENERIC manager classes, e.g.
Now a lot of people ask HOW can this generic stuff work. I'm not going to delve into how the OR-mapper vendors do this stuff, but I will give an example of some generic code using the factory pattern. (excuse my C#)
You will still do a lot of CRUD this way but its more organized. Let the flaming begin [:|]
funkybeatz
Member
345 Points
70 Posts
Re: Is this the right way to insert new item
May 23, 2005 12:52 PM|LINK
azamsharp
All-Star
24614 Points
4612 Posts
Re: Is this the right way to insert new item
May 23, 2005 01:59 PM|LINK
I don't understand that why anyone would like to change the name of the columns in the database. This is a very very huge change that will reflect throughout the application.
To EVO:
Thanks a lot EVO. I will look into the code you gave me. Also is the code below being generated by the OR/MAPPERS or you have to type it manually. I don't have any access to OR/MAPPERS and I have never used them yet but would like to.
HighOnCoding
evo
Participant
840 Points
168 Posts
Re: Is this the right way to insert new item
May 23, 2005 02:13 PM|LINK
My 2 cents regarding the whole "Column change" argument is this:
ALMOST any database schema change is going to be reflected in every layer of the application. For example, adding a column, removing a column, etc. 99% of columns map to business attributes so if you add a column, for example "SSN", you are going to be adding a new property in your BLL, and you are going to be adding a new label or textbox in your UI. It's that simple.
The only changes which MAY not be reflected in every layer are simple changes like adding a default value to a column, tuning your database with indexes, and the like.
How often do people rename columns? NOT VERY and when they do rename them, it's probably because they mispelled a word or violated some sort of design guideline which means they are going to be re-architecting more than just the DAL.
----
I digress. Anyways, regarding code generation - yes, you can use a code generator to make your Manager classes. As Thona pointed out in a previous post, code gens aren't the be-all end-all and you don't get a lot of the features that come with a good OR-Mapper.
Try to keep the following in mind however - if you have a good separation of responsibility through proper layering, you can get away with using the Manager system as demonstrated above and don't have to worry about performance until it becomes an issue. Using a generic DAL (ObjectManager) allows you to write the bare minimal and later go back and tune without rewriting your UI or BLL layers.
Don't assume performance is an issue until it really is an issue. You don't need a OR-Mapper just because everyone says you should use one. A well designed application will be easy to maintain and isolate changes. That's the real goal. OR-Mappers just facilitate this process.
thona
Member
20 Points
2923 Posts
Re: Is this the right way to insert new item
May 23, 2005 03:04 PM|LINK
Also is the code below being generated by the OR/MAPPERS or you have to type it manually.
Wrong. An O/R mapper would not generate the above code. The above code is repetitive, and as such would be handled ina generic way. There is no need to have more than one type of ObjectManager.
I don't have any access to OR/MAPPERS
Wrong. Unless you have someone type in your texts posting on this forums indicates access to the internet. All O/R mapper vendors have websites. Plus there are open source projects. Whether you choose to ignore them or not, you DO have access to them.
azamsharp
All-Star
24614 Points
4612 Posts
Re: Is this the right way to insert new item
May 23, 2005 04:39 PM|LINK
Thanks a million again.
HighOnCoding
evo
Participant
840 Points
168 Posts
Re: Is this the right way to insert new item
May 23, 2005 05:01 PM|LINK
Hmmm... books, good question. Let's see, I got the Object Primer and Building Object Applications that Work by Scott Ambler, the Object Primer is very basic, but BOATW is a pretty decent read for overall OOP.
Most of the MS books are going to advocate a Dataset oriented approach and should be avoided.
Expert One-On-One Business Objects by Lhotka is OK for its information on remoting, but a lot of the stuff regarding OOP is flawed - e.g. putting CRUD directly in the object.
I haven't really found a good book on architecture as far as .NET goes, but if you do a search for books/articles on Java architecture, you are going to find a lot of things. Java has been around for a lot longer and naturally has a lot of stuff regarding architecture available. The two platforms are similar enough that I'm sure you can make the connections.
exptrade2000
Contributor
3309 Points
710 Posts
Re: Is this the right way to insert new item
May 23, 2005 07:24 PM|LINK
I would suggest that you take a look at DotNetNuke and see how persisting and loading objects is handeled in there. That will get you on the right track, and once you understand how it works. If you want to do DDD I would suggest looking at NHibernate open source O/R Mapper.
Here is example of how it is done in DNN ( in my classes I user Persist method that knows if data needs to be inserted or updated)
DocumentInfo
Public Property ItemId() As Integer
Get
Return _ItemId
End Get
Set(ByVal Value As Integer)
_ItemId = Value
End Set
End Property
DocumentController
Public Sub AddDocument(ByVal objDocument As DocumentInfo)DataProvider.Instance().AddDocument(objDocument.ModuleId, objDocument.Title, objDocument.Url, objDocument.CreatedByUser, objDocument.Category)
End Sub
DataProvider
Public MustOverride Function AddDocument(ByVal ModuleId As Integer, ByVal Title As String, ByVal URL As String, ByVal UserName As String, ByVal Category As String) As IntegerSqlDataProvider
Public
Overrides Function AddDocument(ByVal ModuleId As Integer, ByVal Title As String, ByVal URL As String, ByVal UserName As String, ByVal Category As String) As IntegerReturn CType(SqlHelper.ExecuteScalar(ConnectionString, DatabaseOwner & ObjectQualifier & "AddDocument", ModuleId, Title, URL, UserName, Category), Integer)
End Function