Friday, August 15, 2008

Dealing with the Database

Here is my current idea on how to deal with the database.

Mark the Class and Fields with Attributes
The Developer creates the class and adds a few attributes.

  [Database("SampleDatabase")]
  public partial class User
  {
    [Key]
  private string name;

    [Required]
  private string password;
  }

The attributes indicate how to connect the object to a database and how to handle the fields. The class is marked as partial so that generated code can be added to it.

Run a Tool
A tool is used on this class to generate the constructor, the public accessor properties, the Read, Write, Exists and Delete methods, the stored procedures used by these methods, and the create table script.

Questions About the Tool
What is this tool?  Is it run as part of the build script?  Is it a stand-alone tool?  Is it a plug-in to Visual Studio?  Does it use the text of the class as input? Or, does it work off a compiled class?  Can the other parts of the class be generated at run time?

When does the tool run again? Is it automatically part of the build process? Or, does it need to be run manually?

A Similar Tool
I worked on a similar tool, called CSFromXSD, that took an XSD file as input and generated classes that would serialize and de-serialize objects to and from XML files that conformed to the schema described in the XSD.  The XSD was part of the CSProj, and the dependencies were setup such that if the XSD was modified, the associated, generated CS file was regenerated.

This idea of starting with a CS file is a little different.  This would be generating CS-from-CS; therefore, the parsing is not an XML parsing process.  It would be handy to have the original CS file compiled so that I could use reflection on it.

I thought of this CSFromXSD when I came up with this CSFromCS idea. However, I may want to take a different approach on this tool.

Developer View
In the long run, what I am shooting for is that the Developer creates a class (or class description) identifying the name of the class and the fields that need to be persisted and the necessary database scripts and the code to interact with the database are generated.  If the input class (or class description) is modified, the scripts and code are automatically regenerated including some sort of process to update the database.

The Developer then interacts with the class a very natural way.

  if (User.Exists(username)) 
  {
    throw new Exception("User already exists."); 
  }  

  User user = new User(username, password);
  user.Write();

  string name = user.Name;
  string password = user.Password;

  user.Password = "P@55w0rd";
  user.Write();

  User user2 = User.Read(username);

  User.Delete(username);

When another field is added to the User class, the creation and update scripts are generated, the class is regenerated, and the Developer runs the scripts on the database.  Then the Developer can use the new fields in a natural way.

  User user = new User(username, password)
  {
    emailAddress = emailAddress
  }

  user.Write();

No comments: