Using DevExpress XPO in asp.net websites

For several months i developed applications using the wonderful XPO persistent objects library. This month i had to develop a website for an important customer and, satisfied by the XPO performances, i decided to use it for the website too. I developed the full website the same way i developed applications and everything worked fine but when i published it and users started to navigate the website i had serious troubles. The reason is that using XPO in a desktop application is fine considering that the SESSION is just for one user so the data will be always up to date. Using a single SESSION in a web application is impossible because the session objects will be accessed by multiple threads and the data could change while we’re working on it. When we load a persistent object it will have an unique identifier in the session but what if someone else does something that make change this identifier? It happens that XPO generates an error saying “trying to access a disposed object”.
How we can use XPO in a web application?
The first step is creating a DAL object and store it in Application (the same for all the website’s sessions)
The DAL is the XPO data abstraction layer. We’ll create a specific DAL based on our database structure (it’s automatically done by XPO don’t be scared)
We’ll write this specific code in the Global.asax file.
Global.asax

First of all we need to get the connection string to our database (i used mysql)
Dim conn As String = DevExpress.Xpo.DB .MySqlConnectionProvider.GetConnectionString (DBHost, DBUser, DBPass, DBName)

Second step is to obtain the DataStore Schema
Dim dict As New DevExpress.Xpo.Metadata.ReflectionDictionary()
dict.GetDataStoreSchema(GetType(CommunityUser).Assembly)
‘Here i used the type CommunityUser, it’s an XPObject derived class, you can use one of your own classes, doesn’t matter which one you use, it’s just necessary to obtain the assembly, just use one of your persistent objects 😉

Dim store As DevExpress.Xpo.DB.IDataStore = DevExpress.Xpo. XpoDefault.GetConnectionProvider (conn,  DevExpress.Xpo.DB.AutoCreateOption. SchemaAlreadyExists)

Now that you obtained the DataStore interface you can create the DAL, we’ll call it layer
Dim layer = New DevExpress.Xpo.ThreadSafeDataLayer (dict, store)

Last step, store the layer in an application variable, we need it to create connections in the whole website
Application.Add(“XpoLayer”, layer)

We finished with the Global.asax file, now we just need to do the rest in each aspx page.

‘Use this variable in each web page
Dim theSession As Session

In the Page Load sub create the Session object to access the persistent objects of your website.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        theSession = New Session( DirectCast( Application(“XpoLayer”), DevExpress.Xpo.ThreadSafeDataLayer ))
end sub

Last thing to do in your webpages is to override the sub Render to dispose the theSession Object created in the page load event.

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
        MyBase.Render(writer)
        theSession.Dispose()
End Sub

These steps need to be done in each web page accessing persistent objects.
Remember that you need an extra work too, each of your persistent classes needs the new constructor to accept a session object as parameter, we need it to don’t use the default session object.

Public Sub New(ByVal session As Session)
     MyBase.New(session)
End Sub

I hope i’ve been clear enough and that it could be useful.



Comments are closed.