FAQ
This page contains some common questions and answers that have been asked over the years to help people on there way.
Q1. If I would like to extend the generated code where can I do this?
When FrameworkGen generates the various classes within each project it will create PartialClasses and PartialInterfaces folders as required.
The files that live within these folders will not be overwrote once they have been created so any custom functionality can be placed in these classes/interfaces. These classes/interfaces have the suffix 'Ex'.
Q2. Can I modify the code generation templates to customize the generated code?
FrameworkGen has always been a hobby project and because of this was not built to be extensible. Unfortunately all of the code that is generated is hard coded and therefore can not be customised.
Q3. Can I use inline SQL?
You can use inline SQL but FrameworkGen will not generate code that uses inline SQL. When I first started developing I was taught that it was always best practise to use stored procedures for CRUD and general queries.
Mainly because the SQL statements are compiled, it can help prevent SQL injection attacks and also because users/roles can be granted/denied access to various parts of the database. In an enterprise environment I would personally consider it best practise
to grant a user no direct access to tables but to grant access through roles to specific stored procedures. I am not saying this is necessarily the right way but it is my prefered way!
To use inline SQL you can modify the partial class for the data component you would like to add an inline sql method. An example of the code to do this is below. If you would like to use the generated BuildEntities method for the data component do not specify the delegate.
public CustomEntities InlineSqlMethod()
{
return Load<CustomEntities>(CommandType.Text, "SELECT [Column1], [Column2] FROM [CustomTable]",
new DataParameters(), BuildCustomEntities);
}
private IEntities BuildCustomEntities()
{
CustomEntities customEntities = new CustomEntities();
IDataReader reader = DataReader;
try
{
List<string> columns = GetReaderColumns(reader);
int column1Ordinal = columns.IndexOf("Column1");
int column2Ordinal = columns.IndexOf("Column2");
while (reader.Read())
{
CustomEntity customEntity = new CustomEntity();
if (column1Ordinal != -1)
customEntity.Column1 = reader.GetString(column1Ordinal);
if (column2Ordinal != -1)
customEntity.Column2 = reader.GetInt32(column2Ordinal);
customEntities.Add(customEntity);
}
}
catch (Exception ex)
{
HandleException(ex, ex.Message + " An error occurred while trying to populate the 'CustomEntity' entity object from the reader.");
}
return customEntities;
}
Q4. How do I configure the entity caching support?
When entity caching is enabled in FrameworkGen (This can be enabled by selecting the
AddEntityCachingSupport preference) the following app.config file will be created that sits within the solution items folder of the solution. The app.config file contains the following settings:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="Entities_CommandTimeout" value="30" />
<add key="Entities_DataComponentsInversionOfControlFilePath" value="C:\FrameworkGen\Working\SolutionItems\DataComponentsInversionOfControl.config" />
<add key="Entities_EntityCachingEnabledDefault" value="false" />
<add key="Entities_CacheDurationInMinutes" value="1440" />
<add key="Entities_CachingProviderFullTypeName" value="ElencySolutions.ESSurvey.BusinessComponents.CachingProvider" />
<add key="Entities_SqlCacheDependenciesEnabled" value="false" />
<add key="Entities_SqlCacheDependenciesDatabaseName" value="ESSurvey" />
</appSettings>
<connectionStrings>
<add name="ESSurvey_Connection" connectionString="server=TEST-PC\SQLEXPRESS;database=ESSurvey;User ID=sa;Password=v3ry53cur3!;Application Name=ElencySolutions.ESSurvey" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<caching>
<sqlCacheDependency pollTime="10000" enabled="true">
<databases>
<add connectionStringName="ESSurvey_Connection" name="ESSurvey" />
</databases>
</sqlCacheDependency>
</caching>
</system.web>
</configuration>
The settings that are relevant to caching are:
- Entities_EntityCachingEnabledDefault - This specifies whether caching is enabled on all business objects.
- Entities_CacheDurationInMinutes - This specifies the default cache duration in which entity objects should be stored in cache.
- Entities_CachingProviderFullTypeName - This allows the user to specify a caching provider that should be used for caching. Caching providers must implement the ICachingProvider interface.
- Entities_SqlCacheDependenciesEnabled - This specifies whether sql cache dependencies should be used against tables for all business objects.
- Entities_SqlCacheDependenciesDatabaseName - This specifies the name of the database that should be used for sql cache dependencies. This setting relates to the sqlCacheDependency element in the app.config.
Executing Cached Queries
If the app setting
Entities_EntityCachingEnabledDefault has been set to true, you will be able to execute cache queries like the following:
Users users = new Users();
using (UserManager userManager = new UserManager())
{
users = userManager.GetAll();
}
If the app setting
Entities_EntityCachingEnabledDefault has been set to false, you can enable caching on your business object in the following ways:
1. Pass the caching enabled parameter into the business object
Users users = new Users();
using (UserManager userManager = new UserManager(true))
{
users = userManager.GetAll();
}
2. By setting the
CachingEnabled property on the business object
Users users = new Users();
using (UserManager userManager = new UserManager() { CachingEnabled = true })
{
users = userManager.GetAll();
}
3. By modifying the Initialise method in the generated business objects partial class to enable the caching.
/// <summary>
///
/// </summary>
public sealed partial class UserManager
{
private bool _initialised;
protected void Initialise()
{
if (_initialised)
return;
_initialised = true;
CachingEnabled = true;
}
}
The cache duration can also be modified in the following 2 ways:
1. By setting the CacheDurationInMinutes property on the business object
Users users = new Users();
using (UserManager userManager = new UserManager() { CacheDurationInMinutes = 60 })
{
users = userManager.GetAll();
}
2. By modifying the Initialise method in the generated business objects partial class to change the cache duration.
/// <summary>
///
/// </summary>
public sealed partial class UserManager
{
private bool _initialised;
protected void Initialise()
{
if (_initialised)
return;
_initialised = true;
CacheDurationInMinutes = 60;
}
}
Executing Cached Queries with Sql Cache Dependencies
Cached queries can also be configured to make use of sql cache dependencies which can be useful in a load balanced/web farm environment.
A batch file 'SetupSqlCacheDependencies.bat' will be generated by FrameworkGen to enable sql cache dependencies. This will create dependencies against all selected tables in the database. You will need to modify this so that only the tables you require sql caching dependencies applied against are set up. The batch file content looks like the following:
@ECHO OFF
set SERVER=TestServer
set DATABASE=TestDatabase
set USERNAME=TestUser
set PASSWORD=TestPassword!
rem Enabling cache dependencies for database 'TestDatabase'.
"%WINDIR%\Microsoft.NET\Framework\v3.5\aspnet_regsql.exe" -ed -S %SERVER% -d %DATABASE% -U %USERNAME% -P %PASSWORD%
rem Enabling cache dependencies for table 'Answer'.
"%WINDIR%\Microsoft.NET\Framework\v3.5\aspnet_regsql.exe" -et -S %SERVER% -d %DATABASE% -U %USERNAME% -P %PASSWORD% -t Answer
If the app setting
Entities_SqlCacheDependenciesEnabled has been set to true, you will be able to execute cache queries like the following:
Users users = new Users();
using (UserManager userManager = new UserManager())
{
users = userManager.GetAll();
}
If the app setting
Entities_SqlCacheDependenciesEnabled has been set to false, you can enable sql cache depencies caching on your business object in the following ways:
1. By setting the SqlCacheDependenciesEnabled property on the business object.
Users users = new Users();
using (UserManager userManager = new UserManager() { SqlCacheDependenciesEnabled = true })
{
users = userManager.GetAll();
}
2. By modifying the Initialise method in the generated business objects partial class to enable the caching.
/// <summary>
///
/// </summary>
public sealed partial class UserManager
{
private bool _initialised;
protected void Initialise()
{
if (_initialised)
return;
_initialised = true;
SqlCacheDependenciesEnabled = true;
}
}
Q5. How would I add a new stored procedure to a data component?
You can add a new stored procedure call to a data component either by added the procedure through the FrameworkGen GUI or by modifying the partial class for the data component you would like to add an inline sql method. An example of the code to do this is below. If you would like to use the generated BuildEntities method for the data component do not specify the delegate.
public CustomEntities StoredProcMethod()
{
return Load<CustomEntities>("usp_GetData", new DataParameters(), BuildCustomEntities);
}
private IEntities BuildCustomEntities()
{
CustomEntities customEntities = new CustomEntities();
IDataReader reader = DataReader;
try
{
List<string> columns = GetReaderColumns(reader);
int column1Ordinal = columns.IndexOf("Column1");
int column2Ordinal = columns.IndexOf("Column2");
while (reader.Read())
{
CustomEntity customEntity = new CustomEntity();
if (column1Ordinal != -1)
customEntity.Column1 = reader.GetString(column1Ordinal);
if (column2Ordinal != -1)
customEntity.Column2 = reader.GetInt32(column2Ordinal);
customEntities.Add(customEntity);
}
}
catch (Exception ex)
{
HandleException(ex, ex.Message + " An error occurred while trying to populate the 'CustomEntity' entity object from the reader.");
}
return customEntities;
}
Q6. Where can I put my business rules validation code?
FrameworkGen generates many partial classes and interfaces which end in the suffix 'Ex'. FrameworkGen places validate methods within the partial classes for business components. These methods are called by the main business components. You can place any custom business rules validation logic in these validation methods and throw a BusinessRulesValidationException if validation fails.
Q7. How would I ExecuteNotQuery against a stored procedure in a data component?
You can either do this by using the FrameworkGen 'Existing Procedures' form and selecting Execute as the Type or you can modify the partial class for the data component, an example of this is below:
public int TestExecuteNonQuery(int id)
{
DataParameters parameters = new DataParameters();
parameters.Add(new DataParameter("Id", id, DbType.Int32));
return ExecuteNonQuery("usp_Test", parameters);
}
Q8. How would I ExecuteScalar against a stored procedure in a data component?
You can either do this by using the FrameworkGen 'Existing Procedures' form and selecting Scalar as the Type and selecting the Return Type or you can modify the partial class for the data component, an example of this is below:
public int TestExecuteScalar(int id)
{
DataParameters parameters = new DataParameters();
parameters.Add(new DataParameter("Id", id, DbType.Int32));
return ExecuteScalar<int>("usp_Test", parameters);
}
Q9. How would I populate a DataTable in a data component?
You can do this by either selecting the Preference CreateDataTableMethods (this will generate method calls against all stored procedures that return data tables or you could modify the partial class for the data component, an example of this is below:
public DataTable TestPopulateDataTable(int id)
{
DataParameters parameters = new DataParameters();
parameters.Add(new DataParameter("Id", id, DbType.Int32));
DataTable table = new DataTable();
Load(table, "usp_Test", parameters);
return table;
}
Q10. How do I add an output parameter and retrieve it's value in a data component?
An example of doing this is below:
public double TestOutputParameters(int id)
{
DataParameters parameters = new DataParameters();
parameters.Add(new DataParameter("Id", id, DbType.Int32));
parameters.Add(new DataParameter("Total", 0, DbType.Currency, ParameterDirection.InputOutput));
int recordCount = ExecuteNonQuery("usp_Test", parameters);
return parameters.GetParameterValue<double>("Total");
}