I am trying to work out the best way to design a class that has its properties persisted in a database. Let\'s take a basic example of a Person
. To create a new per
First, I'd put two distinct public constructor to Person:
namespace BusinessLayer
{
class Person
{
public Person(string firstName, string lastName): this(firstName, lastName, DateTime.Now)
{}
public Person(string firstName, string lastName, DateTime birthDate)
{
FirstName = firstName;
LastName = lastName;
DateOfBirth = birthDate;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}
}
this allows you to write both
var p = new Person("Marilyin", "Manson");
var p2 = new Person("Alice", "Cooper", new DateTime(...));
and
var p = new Person { FirstName="Marilyn", LastName="Manson" };
I can't see why you should limit to only one form.
As for the DatabaseComponent I'd strongly suggest to write a method that allows you to save a Person instead of the signature you are implicitly declaring.
That's because, should one day change the way a Person is defined, you'd probably have to change the code in each point you invoke Save()
method. By saving just a Person, you only have to change the Save()
implementation.
Don't you plan to use an ORM by the way?
This should be checked by using business rules.
I mean if you want a very re-usable business model, business objects should be re-used elsewhere in different areas, and this may mean same class "A" could be fine in state "X" in some business, but in another situation, same class "A", will be fine in state "Y".
There's a good design pattern allowing you to implement business validators called Specification:
This can be implemented in a lot of ways, but one of most compact ones is by building rules with lambda expressions.
For example:
someAInstance => someAInstance.Name != null && someAInstance.Age > 30
Another way is using existing object validation libraries, like NHibernate Validator, which can be used standalone without NHibernate and allows you to put attributes in class' properties like [NotNull]
, [NotNullNotEmpty]
, and more complex rules, and you can either use built-in ones or you can build your own ones.
Learn more by reading this article (there you'll find a list of out-of-the-box validation rules):
Note that one of most important advantages of NH Validator is it can be used in any layer, not only data or business layer, and as you can use it without NHibernate, you've a light-weight, easy-to-use and multi-layered object validator.
With C# 3.0 class initializers I no longer bother of providing a constructor that allows me to initialize all properties:
var person1 = new Person
{
FirstName = "Kate";
LastName = "Middleton";
};
As far as the Save
method is concerned I usually put them in a separate repository class:
public int Save(Person person)
{
...
}
and then when I need to save a person I do:
var person1 = new Person
{
FirstName = "Kate";
LastName = "Middleton";
};
var id = new PersonsRepository().Save(person1);
Only use constructors if some fields are mandatory since it's an effective way to make sure that those fields are specified.
I'm unsure as to whether the fields should be public or not
Fields usually means member variables and those should always be private. As for properties I would stick with get/set for database objects.
I'm also wondering how I should be dealing with the optional properties of the class. Once the fields have been populated how do I then save them to the DB?
Saving things to the database is a whole different story. I would not try to invent my own layer but to use an existing one. There are a whole set of different ORM:s out there from very simple to very feature complete.
Take a look at PetaPoco for a lightweight alternative or nHibernate for a more feature complete alternative.
Validation
One common way to make sure that mandatory fields are correctly specified and got valid values are to use a validation framework. There is one built into .net called DataAnnotations. Google it and look at some examples.