Connect to a Data Store
- 9 minutes to read
#Prerequisites
To use XPO with your database server, add a required database provider assembly to your project’s references. See the following topic for details: Database Systems Supported by XPO.
#Specify Connection Settings
Call the GetDataLayer(String, AutoCreateOption) method and pass a connection string or existing connection object to this method as a parameter. This method creates a Data Access Layer (DAL) object.
Use the newly created DAL to create UnitOfWork or Session objects:
using System;
using System.Linq;
using DevExpress.Xpo;
namespace XpoConsoleApp {
class Program {
static void Main(string[] args) {
// Connect to an in-memory source
const string connectionString = @"XpoProvider=InMemoryDataStore;Data Source=.\mydatabase.xml;Read Only=false";
var inMemoryDAL = XpoDefault.GetDataLayer(connectionString, DevExpress.Xpo.DB.AutoCreateOption.DatabaseAndSchema);
// Create and save a new data object
using(var uow = new UnitOfWork(inMemoryDAL)) {
var contact = new Contact(uow);
contact.FirstName = "Alice";
contact.LastName = "Smith";
uow.CommitChanges();
}
// Read the new data object
using(var uow = new UnitOfWork(inMemoryDAL)) {
var contact = uow.Query<Contact>().FirstOrDefault(c => c.LastName == "Smith");
Console.WriteLine(contact.FirstName + " " + contact.LastName);
}
}
}
public class Contact : XPObject {
public string FirstName {
get { return fFirstName; }
set { SetPropertyValue(nameof(FirstName), ref fFirstName, value); }
}
string fFirstName;
public string LastName {
get { return fLastName; }
set { SetPropertyValue(nameof(LastName), ref fLastName, value); }
}
string fLastName;
public Contact(Session session) : base(session) { }
}
}
#Share Connection - Default Data Access Layer
You can create a default DAL and use it in any scope of your application.
Use the XpoDefault.DataLayer static property to get or set a default data layer.
To use a default DAL, create UnitOfWork or Session objects using parameterless constructors:
using System;
using System.Linq;
using DevExpress.Xpo;
namespace XpoConsoleApp {
class Program {
static void Main(string[] args) {
// Connect to an in-memory source
const string connectionString = @"XpoProvider=InMemoryDataStore;Data Source=.\mydatabase.xml;Read Only=false";
XpoDefault.DataLayer = XpoDefault.GetDataLayer(connectionString, DevExpress.Xpo.DB.AutoCreateOption.DatabaseAndSchema);
// Create and save a new data object
// This Unit of Work uses a default Data Access Layer
using(var uow = new UnitOfWork()) {
var contact = new Contact(uow);
contact.FirstName = "Alice";
contact.LastName = "Smith";
uow.CommitChanges();
}
// Read a data object
// This Unit of Work uses a default Data Access Layer
using(var uow = new UnitOfWork()) {
var contact = uow.Query<Contact>().FirstOrDefault(c => c.LastName == "Smith");
Console.WriteLine(contact?.FirstName + " " + contact?.LastName);
}
}
}
public class Contact : XPObject {
// ...
public Contact(Session session) : base(session) { }
}
}
Tip
You can also specify a connection string in the following ways:
- Pass a connection string to the Xpo
Default. property.Connection String - Create a new Session or Unit
Of and pass a connection string to the ConnectionWork String property.
Refer to the property descriptions for more information.
#Establish Connection
A connection to a data store is established in the following cases:
- When you use the XpoDefault.GetDataLayer method to create a new DAL or the XpoDefault.GetConnectionProvider method to create a connection provider.
- When the Connect() method is called (if ConnectionString or Connection is specified).
- Before saving or retrieving a persistent object (if ConnectionString or Connection is specified).
If you use the XpoDefault.GetDataLayer or XpoDefault.GetConnectionProvider method, XPO keeps the connection open until the application is stopped or restarted.
To change the database connection without restarting the application, use the following overloaded methods:
- GetDataLayer(String, XPDictionary, AutoCreateOption, out IDisposable[])
- GetDataLayer(IDbConnection, XPDictionary, AutoCreateOption, out IDisposable[])
- GetConnectionProvider(String, AutoCreateOption, out IDisposable[])
These methods have an additional out parameter that initializes a variable with an array of IDisposable objects: objectsToDisposeOnDisconnect
.
using DevExpress.Xpo;
using DevExpress.Xpo.DB;
using DevExpress.Xpo.Metadata;
// ...
static IDisposable[] ObjectsToDisposeOnDisconnect;
static Lazy<XPDictionary> SharedDictionary = new Lazy<XPDictionary>(CreateSharedDictionary);
static void ChangeConnection(string connectionString) {
if(ObjectsToDisposeOnDisconnect != null) {
foreach(IDisposable toDispose in ObjectsToDisposeOnDisconnect)
toDispose.Dispose();
}
XpoDefault.DataLayer = XpoDefault.GetDataLayer(connectionString, SharedDictionary.Value, AutoCreateOption.SchemaAlreadyExists, out ObjectsToDisposeOnDisconnect);
}
static XPDictionary CreateSharedDictionary() {
XPDictionary result = new ReflectionDictionary();
result.GetDataStoreSchema(typeof(Contact).Assembly);
return result;
}
If you want to control the connection state (open/closed), create an IDbConnection
object and use a constructor to pass the object to a Data Store Provider.
using DevExpress.Xpo;
using DevExpress.Xpo.DB;
using Microsoft.Data.SqlClient;
// ...
SqlConnection Connection;
void Connect(string connectionString) {
Connection = new SqlConnection(connectionString);
MSSqlConnectionProvider dataStoreProvider = new MSSqlConnectionProvider(Connection, AutoCreateOption.SchemaAlreadyExists);
XpoDefault.DataLayer = new SimpleDataLayer(dataStoreProvider);
}
If you use the ConnectionString or Connection property, the connection is alive while a session is active (until the Session.Disconnect method is explicitly called). This method is called implicitly when you dispose of a Session object.
#How It Works
#Data Store Provider
A data store provider is an IDataStore implementation. It connects individual data stores (Microsoft SQL Server, MySQL databases, etc.)
See also: DataStoreBase.
#Data Access Layer
A data access layer (DAL) (an IDataLayer implementation) uses object access layers to enable a unified access to data stores (loading data from a data store, updating its data and schema).
#SimpleDataLayer and ThreadSafeDataLayer
XPO includes the following data access layer implementations:
- SimpleDataLayer - the default implementation.
- ThreadSafeDataLayer.
In general, SimpleDataLayer is equal to ThreadSafeDataLayer, and the substitution of one component by another has no effect. However, you cannot use SimpleDataLayer or ThreadSafeDataLayer under the circumstances described below:
- SimpleDataLayer does not support concurrent access from multiple threads. Use ThreadSafeDataLayer in multi-threaded applications and web applications where you share a data access layer between multiple users. Use ThreadSafeDataLayer if you use XPInstantFeedbackSource and XPInstantFeedbackView data sources.
- ThreadSafeDataLayer implies that you never add new classes to XPDictionary or modify XPO metadata at runtime. You should add all required classes to XPDictionary before you create ThreadSafeDataLayer. You cannot dynamically create new classes/properties or add attributes after you instantiate a ThreadSafeDataLayer object.
- ThreadSafeDataLayer does not support Database Level Transactions.
See also: How to Resolve ‘Cannot Modify Dictionary because ThreadSafeDataLayer Uses It’
#Share DAL for Performance Optimization
Each Session or UnitOfWork object creates a new DAL when a connection to a data store is about to be established. You can force a Session or UnitOfWork to use an existing DAL. In this case, specific initialization steps are omitted and the connection is established faster.
To make a session use a specific DAL, do one of the following:
- Assign the DAL to the XpoDefault.DataLayer property. All newly created sessions whose DALs are not initialized use the default DAL.
- Pass the DAL to the Session or UnitOfWork object’s constructor.
- Pass the DAL to the Connect method of a Session or UnitOfWork object (see Session.Connect for details) to establish a connection to a data store.
See also: IDataLayerAsync.
#Object Access Layer
An object access layer (OAL) is a mediator between a Session or UnitOfWork and a data access layer. An OAL translates object queries and storage schema updates to corresponding statements, and passes them to a data access layer for execution.
XPO has the following object access layer implementations.
- SimpleObjectLayer - Created for a session or unit of work. This object layer uses a data access layer as a data source.
- SessionObjectLayer - Created for nested units of work. This object layer uses a parent unit of work as a data source.
- SerializableObjectLayerClient - Available for applications that use WCF, .NET Remoting, etc. to transfer data. This object layer uses the SerializableObjectLayer class or any other class that implements the ISerializableObjectLayer interface as a data source.
See also: IObjectLayerAsync.
#Concepts
- Cached Data Store
- Transfer Data via REST API
- Transfer Data via WCF Services
- Data Types Supported by XPO
Note
You can try the functionality described here in the Connecting to a Data Store section of the XPO Tutorials demo (C:\Users\Public\Documents\DevExpress Demos 24.