In this blog post I will show you how to configure a single Fluent Model in order to connect to a database with the same schema on both Microsoft SQL Server and SQLite. There are two main steps you must take in order to do this:
This is the key step when configuring the model to work with both SQL Server and SQLite. Backend independent type mapping can be achieved by using the WithOpenAccessType method when mapping the persistent properties of your classes to database columns. For example, consider a class User which has a decimal property Income. This property can be mapped to column independently from the backend with the following code snippet:
userMappingConfig.HasProperty(usr => usr.Income).WithOpenAccessType(OpenAccessType.Decimal)
.ToColumn("Income").HasPrecision(12).HasScale(2);
When the OpenAccessType is set using this method, Telerik Data Access will automatically determine the SQL type of the respective database column depending on the backend currently used by the model. This will decouple your mapping configuration from the backend.
To create an instance of the context for a specific backend, we must provide it with the name of the connection string which will be used and a BackendConfiguration object with a specific setup.
A custom constructor that accepts these parameters will be needed in the context class (the one that inherits from OpenAccessContext) of the model. For convenience I will also add an additional parameter along with the respective field and property to denote the mode in which the context instance is working - Online or Offline:
public FluentModel(String connectionStringName, BackendConfiguration backendConfiguration, ContextMode contextMode)
: base(connectionStringName, backendConfiguration, metadataSource)
{
this.mode = contextMode;
}
private ContextMode mode;
public ContextMode Mode
{
get
{
return this.mode;
}
}
public enum ContextMode
{
OnlineMode = 1,
OfflineMode = 2
}
public class ContextFactory
{
private const string ONLINE_STORAGE_CONNECTION_NAME = @"SQLServerConnection";
private const string OFFLINE_STORAGE_CONNECTION_NAME = @"SQLiteConnection";
private static BackendConfiguration onlineBackendConfig;
private static BackendConfiguration offlineBackendConfig;
private static ContextFactory factoryInstance = null;
private ContextMode contextMode = ContextMode.OnlineMode;
public static ContextFactory FactoryInstance
{
get
{
if (factoryInstance == null)
{
onlineBackendConfig = new BackendConfiguration();
onlineBackendConfig.Backend = "MsSql";
onlineBackendConfig.ProviderName = "System.Data.SqlClient";
offlineBackendConfig = new BackendConfiguration();
offlineBackendConfig.Backend = "SQLite";
offlineBackendConfig.ProviderName = "System.Data.SQLite";
factoryInstance = new ContextFactory();
}
return factoryInstance;
}
}
public ContextMode ContextMode
{
get
{
return this.contextMode;
}
}
private ContextFactory()
{
}
public FluentModel GetContext()
{
FluentModel context = null;
if (this.contextMode == ContextMode.OnlineMode)
{
context = new FluentModel(ONLINE_STORAGE_CONNECTION_NAME, onlineBackendConfig, this.contextMode);
}
else
{
context = new FluentModel(OFFLINE_STORAGE_CONNECTION_NAME, offlineBackendConfig, this.contextMode);
}
return context;
}
public void SetContextMode(ContextMode contextMode)
{
this.contextMode = contextMode;
}
}