How to access new data
To access new database tables you will need to create new BusinessObjects and DataProvider classes.
Create a BusinessObject class
There are three options for you to begin:
For a class to be a legal business object class, you only need to inherit from the base DataEntity class:
LSOne.DataLayer.BusinessObjects.DataEntity
You can then add your fields as public properties and make sure that you call the base class constructor to get your functionality ready.
When creating a new data object you have to make sure that you have all the columns the database table has and that they are of the right type..
This is the most common way of creating a business object since there is usually not much in common between different business objects.
You can locate a similar business object class in the BusinessObjects project and use that as a template for your own class.
If you want a simple and concrete sample to start from you can look at the BusinessObject classes from our sample plugin Criminal (located in the development package under Training_materials\Source\Criminals\Solution Criminal Plugin). There are two data entities: Criminal.cs and StolenItem.cs.
Criminal business object sample code walkthrough
The business object Criminal represents the table Criminal, which is created in How to create/edit a database table.
public GenderEnum Gender { get; set; }
public int Age { get; set; }
public System.Drawing.Image Photo { get; set;}
Each field from the database table is added as a public property on the business object class with a getter and setter.
If you look at the database table, Criminal, you will notice that the fields ID and Alias are missing from the property list. The reason is that the fields ID and Text are from the base class DataEntity and will be used to store those two fields.
This is all that is needed for a class to be a legal business object.
Create a DataProvider class
As with the data entities there are three options for you to begin.
First you need to make the interface. The interface inherits from IDataProviderBase<T> where T is your business object. For example the interface for the Criminal data provider looks like this:
public interface ICriminalData : IDataProviderBase<DataLayer.DataEntities.Criminal>
The data provider needs to inherit from SqlServerDataProviderBase and implement the interface like you see in the Criminal plugin:
public class CriminalData : SqlServerDataProviderBase, ICriminalData
For best practices please refer to Functions overview for a list of common functions and their specifications.
You can copy an existing DataProvider class and its interface and use that as a template for your own class. You will probably not be able to reuse any data access code because the data provider that you are copying is accessing a different table. It can, however, contain some useful code and a list of basic functions that you need.
If you want to use a simple and concrete sample to start from you can look at the CriminalData.cs or StolenItemData.cs classes from our sample plugin Criminal (located in the development package under Source\Criminals\Solution Criminal Plugin\DataLayer). Those two classes contain the most common functions that any DataProvider class should contain and can serve as a useful template for your own DataProvider class.
LS One uses a factory for its DataProvider classes and you will need to register your DataProvider class to the factory before you can use it in your code. To do this you need to call the register function on the DataProviderFactory.Instance class. For example the CriminalData DataProvider is registered like this:
DataProviderFactory.Instance.Register<ICriminalData,
CriminalData,
DataLayer.DataEntities.Criminal>
This is a list of functions that are most commonly found in any DataProvider class. Note that these functions are not a part of any interface or abstract class but are considered to be a part of best practices when programming for LS One.
Base functions |
Description |
private string BaseSql |
This property contains the base sql select query that is used throughout the DataProvider class. This is used because you are usually selecting the same columns in the functions as you use in the DataProvider, and this makes making modification to the query easier. |
private void PopulateYourDataEntity(SqlDataReader dr, YourDataEntity dataEntity) |
This function is generally called the populator function. In this function you populate the fields in your business object class with the corresponding fields from the SqlDataReader object. This is where you map your database table fields to your DataEntity class. |
public DataLayer.DataEntities.YourDataEntity Get(IConnectionManager entry, RecordIdentifier ID) |
A Get function retrieves the YourDataEntity object that corresponds with the database record with a primary key value that corresponds with ID. This function then uses the populator function above to map the database table to the business object. |
public List<DataLayer.DataEntities. YourDataEntity> GetList(IConnectionManager entry) |
A GetList function retrieves all records from a table and returns a list of corresponding DataEntity objects. The populator function above is also used here to map the database table to the business object. |
public void Delete(IConnectionManager entry, RecordIdentifier ID) |
Deletes a database record where the primary key value corresponds with the value in ID. |
public bool Exists(IConnectionManager entry, RecordIdentifier ID) |
Checks whether a record exists with a primary key value corresponding with the value in ID. |
public void Save(IConnectionManager entry, DataLayer.DataEntities.YourDataEntity dataEntity) |
A Save function serves two purposes: to create a new entry in the database or update an existing record. |
CriminalData data provider code walkthrough
The CriminalData data provider is located in the sample plugin Criminal at Criminal Ø DataLayer Ø CriminalData.cs. This is a good example of a simple data provider class implementation that you can use as a basis for your own data providers.
private string BaseSql
{
get
{
return @"SELECT ID,
ISNULL(ALIAS, '') as ALIAS,
ISNULL(GENDER, 2) as GENDER,
ISNULL(AGE, 0) as AGE,
FROM CRIMINAL "
}
}
This property stores the base sql query to fetch data from the Criminal table. This allows you to reuse the base query in multiple data access functions. Note that the where clause is missing, but this is done so that other functions can concatenate different where conditions based on the purpose of each data access function.
private static void PopulateCriminal(IDataReader dr,
DataLayer.DataEntities.Criminal criminal)
{
criminal.ID = (Guid)dr["ID"];
criminal.Text = (string)dr["Alias"];
criminal.Gender = (GenderEnum)dr["Gender"];
criminal.Age = (int)dr["Age"];
}
This function serves the purpose of populating a Criminal business object with data from the Criminal database table. This function gets a IDataReader object that contains a single row from the Criminal table based on the BaseSql query that is defined above. The second parameter is a Criminal data business object, which is then populated with data from the SqlDataReader.
Next you should go back to Lesson 4 and do the exercise: Lesson 4 - Data access