Current filter:
                                You should refresh the page.
                                  • Description:
                                    This article focuses on the requirements, which must be met for successful use of eXpress Persistent Objects in ASP.NET Web applications.

                                    Answer:
                                    What makes Web and desktop applications different is that the former is a multi-threaded application. This is the point to be kept in mind when you create a Web ASP.NET project with eXpress Persistent Objects.

                                    Note, if you need to create a common persistent layer based on XPO which will be used by both desktop and Web forms applications, you should place all the common code in a shared assembly and refer to this assembly in your applications.

                                    There are several basic rules to follow for XPO to work fine in your ASP.NET application:
                                    1. Create a ThreadSafeDataLayer instance in the entry point of your application and assign it to the static XpoDefault.DataLayer property.
                                    It's similar to Windows Forms development where it's A2944 recommended to initialize XpoDefault.DataLayer in the Main procedure. The differences include:
                                    A) ThreadSafeDataLayer is to be used in ASP.NET, not in a SimpleDataLayer.
                                    B) The database schema must be up-to-date and contain the XPObjectType table. An XPO connection provider must be created with the SchemaAlreadyExists parameter.
                                    C) ThreadSafeDataLayer requires the XPO dictionary (stores persistent objects' metadata) to be initialized at the moment when ThreadSafeDataLayer is created.
                                    D) The Web application's entry point is the Application_Start procedure in Global.asax. However, it's not recommended to use it to initialize XPO DataLayer, because website pages can be opened even if an exception has been thrown within Application_Start.
                                    To sum it up, here is a template for an XpoHelper module, which you can import into your application:

                                    [C#]
                                    using System; using DevExpress.Xpo; using DevExpress.Xpo.DB; using DevExpress.Xpo.Metadata; using System.Configuration; public static class XpoHelper { public static Session GetNewSession() { return new Session(DataLayer); } public static UnitOfWork GetNewUnitOfWork() { return new UnitOfWork(DataLayer); } private readonly static object lockObject = new object(); static volatile IDataLayer fDataLayer; static IDataLayer DataLayer { get { if(fDataLayer == null) { lock(lockObject) { if(fDataLayer == null) { fDataLayer = GetDataLayer(); } } } return fDataLayer; } } private static IDataLayer GetDataLayer() { XpoDefault.Session = null; string conn = ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString; conn = XpoDefault.GetConnectionPoolString(conn); XPDictionary dict = new ReflectionDictionary(); IDataStore store = XpoDefault.GetConnectionProvider(conn, AutoCreateOption.SchemaAlreadyExists); dict.GetDataStoreSchema(System.Reflection.Assembly.GetExecutingAssembly()); IDataLayer dl = new ThreadSafeDataLayer(dict, store); return dl; } }
                                    [VB.NET]
                                    Imports System Imports DevExpress.Xpo Imports DevExpress.Xpo.DB Imports DevExpress.Xpo.Metadata Imports System.Configuration Public NotInheritable Class XpoHelper Public Shared Function GetNewSession() As Session Return New Session(DataLayer) End Function Public Shared Function GetNewUnitOfWork() As UnitOfWork Return New UnitOfWork(DataLayer) End Function Private Shared lockObject As New Object() Private Shared fDataLayer As IDataLayer Private Shared ReadOnly Property DataLayer() As IDataLayer Get If fDataLayer Is Nothing Then SyncLock lockObject If Thread.VolatileRead(fDataLayer) Is Nothing Then Thread.VolatileWrite(fDataLayer, GetDataLayer()) End If End SyncLock End If Return fDataLayer End Get End Property Private Shared Function GetDataLayer() As IDataLayer XpoDefault.Session = Nothing Dim conn As String = ConfigurationManager.ConnectionStrings("ConnectionStringName").ConnectionString conn = XpoDefault.GetConnectionPoolString(conn) Dim dict As XPDictionary = New ReflectionDictionary() Dim store As IDataStore = XpoDefault.GetConnectionProvider(conn, AutoCreateOption.SchemaAlreadyExists) dict.GetDataStoreSchema(System.Reflection.Assembly.GetExecutingAssembly()) Dim dl As IDataLayer = New ThreadSafeDataLayer(dict, store) Return dl End Function End Class

                                    Take special note that you are not limited to a single XpoDefault.DataLayer here and can effectively initialize more than one data layer for your needs - just take in mind that for the best performance you normally need to create one data layer per data store (database) only once and then reuse its cached version in other parts of your application for future calls.

                                    Also, if your database server is not MS SQL Server, you may need to add an additional option to the connection string: XpoProvider. Refer to the following article for details:  How to create a correct connection string for XPO providers.
                                    2. Prevent a mute XpoDefault.Session use by setting it to null (Nothing in VB.NET).
                                    You should reset XpoDefault.Session to null, as shown in the above code snippet, to avoid a mute use of the default XPO session. XPO Session is not a thread-safe object and it mustn't be shared among pages and users in ASP.NET.
                                    3. Acquire a UnitOfWork / Session instance from XpoHelper within the Page_Init method of your Web pages.
                                    This requirement is almost the same as paragraph #4 in A2944. Being just a piece of advice for Windows Forms development, it's a mandatory requirement for ASP.NET: each Web page must use its own UnitOfWork or Session instance.

                                    [C#]
                                    using DevExpress.Xpo; protected void Page_Init(object sender, EventArgs e) { Session session = XpoHelper.GetNewSession(); XpoDataSource1.Session = session; }
                                    [VB.NET]
                                    Imports DevExpress.Xpo Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Dim session As Session = XpoHelper.GetNewSession() XpoDataSource1.Session = session End Sub

                                    In addition to the above 3 requirements, there are some recommendations. First of all, suggestions provided in the A2944 article are also applicable to Web development with XPO. Second, it's highly recommended that you create a separate assembly for your persistent classes (XPObject descendants). If you prefer to maintain all your code within a Web Site project, persistent classes must be placed under the App_Code subfolder. Third, it is necessary to set the XpoDefault.UseFastAccessors property to false and the XpoDefault.IdentityMapBehavior property to IdentityMapBehavior.Strong, if the web site is hosted in partial trust environment.
                                    Please find a sample solution in the attachment. It consists of three projects:
                                    DatabaseUpdater - an application, which creates an XpoWebTest database on your local MS SQL Server, creates schema, and fills it with some sample data. Data from this database is displayed in XpoWebApplication (see below).
                                    PersistentObjects - a Class Library with persistent classes.
                                    XpoWebApplication - a simple Web application which loads XPO data and displays it via a DataView. It includes the XpoHelper module and demonstrates how to implement a Page_Init method.
                                    See Also:
                                    A2944
                                    Tutorial 5 - An ASP .NET Application for Data Editing
                                    Tutorial 6 - A Simple Guestbook (ASP.NET)

                                Show all comments
                                • amit chawla 2 10.08.2012

                                  Hi
                                  I need complete source code the example illustrate below because i can't find the attachment link.
                                  Thanks
                                  Amit

                                • Dennis (DevExpress) 10.09.2012

                                  @Amit:
                                  You can find this source code in the eXpress Persistent Objects > Getting Started help article.

                                • Gabriel St. 07.04.2013

                                  @amit you have code at the right of the site (top of it) in orange square --->

                                • Andreas Mummenhoff 11.04.2013

                                  Why is the implementation in VB different from C# (SyncLock + Thread.VolatileRead/Write vs. only SyncLock)?

                                • Michael (DevExpress Support) 11.05.2013

                                  Implementations are quite different because VB.NET has no equivalent to C#'s volatile keyword.

                                • Dmitriy T 12.06.2013

                                  Hello Nick,
                                  I used XpoHelper like this. Now i want to update it to support multiple databases.
                                  Could you look at my code and say if it is alright? If not, could you provide me with a good example?
                                  Thank you in advance.
                                  using DevExpress.Xpo;
                                  using DevExpress.Xpo.DB;
                                  using DevExpress.Xpo.Metadata;
                                  using DevExpressMvcApplication10.Utils;
                                  using System.Collections.Concurrent;
                                  using System;
                                  public static class XpoHelper
                                  {
                                      public static enum Database { test1 = 0, test2 = 1 };
                                      public readonly static object lockObject = new object();
                                      private static ConcurrentDictionary<Database, IDataLayer> ConcurrentLayerDictionary = new ConcurrentDictionary<Database, IDataLayer>();
                                      public static Session GetNewSession(Database db)
                                      {
                                          return new Session(ConcurrentLayerDictionary.GetOrAdd(db, GetDataLayer(db)));
                                      }
                                      private static Func<Database, IDataLayer> GetDataLayer = db =>
                                      {
                                          lock (XpoHelper.lockObject)
                                          {
                                              XpoDefault.Session = null;
                                              string conn;
                                              XPDictionary dict;
                                              IDataStore store;
                                              IDataLayer dl;
                                              switch (db)
                                              {
                                                  case Database.test1:
                                                      conn = MSSqlConnectionProvider.GetConnectionString("test1", "test1", "test1", "test1") + ";Connect Timeout=60";
                                                      dict = new ReflectionDictionary();
                                                      store = XpoDefault.GetConnectionProvider(conn, AutoCreateOption.SchemaAlreadyExists);
                                                      dict.GetDataStoreSchema(typeof(test1).Assembly);
                                                      break;
                                                  case Database.test2:
                                                      conn = MSSqlConnectionProvider.GetConnectionString("test2", "test2", "test2", "test2") + ";ConnectTimeout=60";
                                                      dict = new ReflectionDictionary();
                                                      store = XpoDefault.GetConnectionProvider(conn, AutoCreateOption.SchemaAlreadyExists);
                                                      dict.GetDataStoreSchema(typeof(test2).Assembly);
                                                      break;
                                                  default:
                                                      throw new Exception("Unknown database");
                                              }
                                              dl = new ThreadSafeDataLayer(dict, store);
                                              return dl;
                                          }
                                      };
                                  }

                                • Michael (DevExpress Support) 12.07.2013

                                  @Dmitriy: I have created a separate ticket for your question: Q463893: XpoHelper for connecting to multiple databases.

                                • Miguel Pichiya 06.07.2014

                                  Greetings Nick from Guatemala City, do you have the samples for version 13 of XPO, or an update for XpoHelper???
                                  Please find a sample solution in the attachment. It consists of three projects:
                                  DatabaseUpdater - an application, which creates an XpoWebTest database on your local MS SQL Server, creates schema, and fills it with some sample data. Data from this database is displayed in XpoWebApplication (see below).
                                  PersistentObjects - a Class Library with persistent classes.
                                  XpoWebApplication - a simple Web application which loads XPO data and displays it via a DataView. It includes the XpoHelper module and demonstrates how to implement a Page_Init method.
                                  Thaks in advance.

                                • Dennis (DevExpress) 06.09.2014

                                  @Miguel: Please take a look at the How to edit a persistent object on a Web page for a ready sample project. I hope this helps.

                                • Tobias Stracke 07.03.2014

                                  Dear Sirs,
                                  I have a short question - I'm a total newby with xpo - sorry for my stupid question...
                                  I have build a Model with the wizzard (see the picture)
                                  How can I put it in the datastoreschema?
                                  Dim conn As String = MSSqlConnectionProvider.GetConnectionString("(local)", "XpoWebTest")
                                        Dim dict As XPDictionary = New ReflectionDictionary()
                                        Dim store As IDataStore = XpoDefault.GetConnectionProvider(conn, AutoCreateOption.SchemaAlreadyExists)
                                  ' how init it here???
                                        dict.GetDataStoreSchema(GetType(PersistentObjects.Customer).Assembly)
                                        Dim dl As IDataLayer = New ThreadSafeDataLayer(dict, store)
                                        Return dl

                                • Michael (DevExpress Support) 07.03.2014

                                  @Tobias: I have created a separate ticket for your question and will answer you there: How can I put it in the datastoreschema?

                                0 Solutions

                                Creation Date Importance Sort by