Skip to main content

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:

Refer to the property descriptions for more information.

#Establish Connection

A connection to a data store is established in the following cases:

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:

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:

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.

See also: IObjectLayerAsync.

#Concepts

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.1\Components\WinForms\Bin\XpoTutorials.exe).

#Task-Based Help