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

                                You must  log in  or  register  to leave comments

                                1 Solution

                                0

                                What makes Web and Windows Forms 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.

                                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; 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 = MSSqlConnectionProvider.GetConnectionString("(local)", "XpoWebTest"); XPDictionary dict = new ReflectionDictionary(); IDataStore store = XpoDefault.GetConnectionProvider(conn, AutoCreateOption.SchemaAlreadyExists); dict.GetDataStoreSchema(typeof(PersistentObjects.Customer).Assembly); IDataLayer dl = new ThreadSafeDataLayer(dict, store); return dl; } }
                                	
                                [VB.NET]
                                Imports System Imports DevExpress.Xpo Imports DevExpress.Xpo.DB Imports DevExpress.Xpo.Metadata 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 = MSSqlConnectionProvider.GetConnectionString("(local)", "XpoWebTest") Dim dict As XPDictionary = New ReflectionDictionary() Dim store As IDataStore = XpoDefault.GetConnectionProvider(conn, AutoCreateOption.SchemaAlreadyExists) dict.GetDataStoreSchema(GetType(PersistentObjects.Customer).Assembly) Dim dl As IDataLayer = New ThreadSafeDataLayer(dict, store) Return dl End Function End Class

                                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)

                                You must  log in  or  register  to leave comments