Jammer.NET - Open Source C# Software Development Framework

Open Source C# Software Development Framework

Archive for the 'Entity (ORM) Layer' Category


Code Generator-Friendly Database Naming Conventions

Posted by Randolph Cabral on Wednesday October 17, 2007

The Jammer.NET Code Generator is currently designed to read tables and stored procedures from a Microsoft SQL Server database and generate C# code files for the entity ORM layer and business layer.  Generating fully functional and error-free code with the code generator is a relatively easy thing to do as long as your database conforms to the following naming conventions.

Table Naming Guidelines 

Prefixes

All tables should be prefixed with the one of the following values according to its contents:

  • “tbl_” – Tables that contain data that will be modified.
  • “ref_” – Tables that contain data for reference purposes only.  Not typically for use with tables that will need updates, inserts, deletes.
  • “rel_” – Tables that contain data about relationships to other tables (typically used for many-to-many relationships).  This prefix is best followed with the name of the Parent table and Child table names without any prefixes or suffixes. (e.g. rel_OrderProduct)
  • “sys_” – Tables that are not referenced by the application code.  For use by database specific jobs and processes only.

Table Name

After the prefix, choose a word, in singular lemmatized form, that best describes the data contained in the table.  Examples:

  • “tbl_Order” – A table that contains order data that can be modified.
  • “tbl_Customer” – A table that contains customer data that can be modified.
  • “ref_ProductType” – A table that contains product type data for reference purposes.
  • “rel_CustomerOrder” – A table that contains a many-to-many relationship based on primary and foreign key constraints of related tables.

Suffixes

There are no recommended table suffixes for the code generator at this time.  So if you need a suffix, go for it.  Note, however, that the code generator will only trim out prefixes.  Names with suffixes separated by underscores will not be trimmed.

Column Naming Guidelines 

Prefixes

All columns should be prefixed according to the following rules:

  • All lowercase.
  • Should not be too long. Use your judgment. It’s a prefix!
  • Must represent an existing table in the form of an abbreviation or an acronym.
  • Be consistent.  Use the same prefix for all tables, columns, and stored procedures across the database.  This rule goes for foreign keys as well.
  • Even for the current table, you should have a prefix that is consistent across all database objects.
  • End all prefixes with an underscore to delimit the prefix with the column name. (e.g. “cust_”)

Column Name

All columns should have a unique name.  After the prefix, choose words, in singular lemmatized form, that best describes the data contained in the column.  Note: The name that follows the prefix should also be unique from other post-prefix names (e.g. “cust_Id” and “pref_Id” would cause the code generator to create two public “Id” properties).  Examples:

  • “cust_Id” – Primary key for the customer table.
  • “pref_PreferenceId” – Foreign key column in the tbl_Customer table to the tbl_Preference table.
  • “cust_Name” – Name column in the tbl_Customer table.

Suffixes

We currently do not recommend the use of suffixes for column names at this time.  So if you need a suffix, go for it.  Note, however, that the code generator will only trim out prefixes.  Names with suffixes separated by underscores will not be trimmed.

Stored Procedure Naming Guidelines 

Prefixes

All stored procedures should be prefixed according to the following rules:

  • All lowercase.
  • Should not be too long. Again, use your judgment. It’s a prefix!
  • Be consistent.  Use the same prefix for all application specific stored procedures across the database.
  • End all prefixes with an underscore to delimit the prefix with the stored procedure name. (e.g. “usp_”, “proc_”, “sync_”)

Stored Procedure Name

All stored procedures should have a unique name.  After the prefix, choose words, in singular lemmatized form, that best describes the table(s) that the procedure will operate on.  Examples:

  • “usp_Tenant_Get” – Gets a single record from the Tenant table.
  • “usp_TenantView_Get” – Gets multiple records from the Tenant table.
  • “sync_TenantImportStep01” – The first of a series of import stored procedures for the Tenant table.

Suffixes

All stored procedures should be suffixed with the one of the following values according to its function:

  • “_Get” – Represents a query stored procedure that returns either a set of records or a single record.
  • “_Insert” – Represents a non-query stored procedure that inserts a single record.
  • “_Update” – Represents a non-query stored procedure that updates a single record.
  • “_Delete” – Represents a non-query stored procedure that deletes a single record.

Posted in Business Layer, Code Generator, Entity (ORM) Layer, Getting Started, How-to | 1 Comment »

How to Create an Entity / Object-relational Mapping

Posted by Randolph Cabral on Saturday August 4, 2007

Entities 

Jammer.NET entities contain all of the mapping metadata in-line with the C# source code.  We’ve found this implementation affords benefits that outweigh any incremental gains of keeping the mapping metadata in a separate file.  Typically, changes made to a database schema are significant enough to require changes to the C# application source anyway.  Let’s face it; how often does a requirement or feature enhancement come along that amounts to changing one column type or name?  Most feature enhancements require a significant schema and application modification that necessitate a redeployment of application code even if the enhancement is as innocuous as adding a secondary email address to a web form.

Inline Metadata Mapping using Custom Attributes

Jammer.NET takes advantage of custom attributes.  Custom attributes are adorned to the appropriate class members to define class member mappings as well as mappings to database objects and the database itself.  The following code sample illustrates how these mappings are declared.

[Database("Northwind")]

[Load("usp_Customers_Get")]

[Save("usp_Customers_Insert", "usp_Customers_Update")]

[Delete("usp_Customers_Delete")]

public partial class Customers : EntityBase, IEntityValidateable

{

  [Key][FieldMap("CustomerID")] private string _CustomerID;

  [FieldMap("CompanyName")] private string _CompanyName;

  [FieldMap("ContactName")] private string _ContactName;

  [FieldMap("ContactTitle")] private string _ContactTitle;

  [FieldMap("Address")] private string _Address;

  [FieldMap("City")] private string _City;

  [FieldMap("Region")] private string _Region;

  [FieldMap("PostalCode")] private string _PostalCode;

  [FieldMap("Country")] private string _Country;

  [FieldMap("Phone")] private string _Phone;

  [FieldMap("Fax")] private string _Fax;

 
The Database attribute defines the name of the connection instance to use which is defined in the <connectionStrings> section of the web or  application configuration file.  The Load, Save and Delete attributes define mappings to specific CRUD stored procedures which only are executed when base methods of the same names are invoked.   The following code sample shows the application configuration file definition.

<connectionStrings>

  <add name=Northwind providerName=System.Data.SqlClient connectionString=server=SERVER;database=DATABASE;uid=USER;pwd=PASSWORD />

</connectionStrings>


The Key() Attribute

The key attribute is used to define the primary key column(s) of a given table.  The usage of the key attribute is demonstrated in the following code sample. 

  [Key][FieldMap("CustomerID")] private string _CustomerID;


The FieldMap() Attribute

Creating mappings to columns in a table or columns returned by a stored procedure are defined by the use of the FieldMap() attribute.  In the following code sample,  the database column “CompanyName” is mapped to a class-level private variable “_CompanyName”.  Note: FieldMap() attributes should only be used on class-level private variables.

  [FieldMap("CompanyName")] private string _CompanyName;


Use Visual Studio IDE “Go To Definition” Functionality

Go To Definition Context MenuOne of the greatest benefits to using inline attribute-based mapping is the ability to use the Visual Studio IDE’s “Go To Definition” feature to navigate to the mapping definitions.  This feature can be used from any tier in the code base as long as the project with the source is included in your solution.  It comes in handy when you need to follow execution logic as well. 

To use this feature, place the cursor at a method or property call, or variable reference and right-click.  Select “Go To Definition” from the context menu and left-click.  Visual Studio will open the corresponding source file and auto-scroll to the proper line where the definition is made.   The image to the right is a screen capture of the context menu in Visual Studio 2005.

To return to the previous cursor location use the control-minus key stroke combination ([CTRL] + [-]).  For more IDE productivity features, you can visit Microsoft’s Visual Studio Developer Center website.

Posted in Entity (ORM) Layer, Getting Started, How-to | 8 Comments »