This topic applies to .NET version only
You can use db4o as a persistent layer of your ASP.NET
application. The actual integration of db4o into your web application is quite
simple: you just need to add reference to Db4objects.Db4o.dll and use it in a client/server mode.
However, as it is characteristic to web-applications in general, there are some security permissions involved, which can in fact forbid db4o functionality in your ASP.NET application. So, before developing/deploying you should make sure that the required permissions would be granted to your application at the hosting server:
Trust Level of your site should be set to "Full".
All the necessary permissions should be granted to db4o assembly. The easiest way to ensure this is to add full trust to db4o:
caspol -af Db4objects.Db4o.dll
If full trust is not a suitable solution for, you can check the minimum security permissions that db4o dll needs to operate using permcalc.exe tool from your Visual Studio installation.
PermCalc.exe -Sandbox Db4objects.Db4o.dll
01<?xml version="1.0"?> 02
<Sandbox> 03
<PermissionSet version="1" class="System.Security.PermissionSet"> 04
<IPermission version="1" class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Read="*AllFiles*" PathDiscovery="*AllFiles*" /> 05
<IPermission version="1" class="System.Security.Permissions.ReflectionPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Flags="MemberAccess" /> 06
<IPermission version="1" class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Flags="UnmanagedCode, Execution, ControlEvidence" /> 07
<IPermission Window="SafeSubWindows" Clipboard="OwnClipboard" version="1" class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 08
<IPermission version="1" class="System.Security.Permissions.KeyContainerPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Unrestricted="true" /> 09
</PermissionSet> 10
</Sandbox>
Consult with your web-server administrator to grant these permissions.
Let's look at an example implementation: we will create a simple ASP.NET application, which will use db4o to store, retrieve and delete objects
The basic requirements for seamless db4o integration are:
In order to keep page-specific code clean we will implement db4o functionality in a separate Db4oHttpModule implementing IhttpModule interface.
Database file path can be saved in Web.Config:
<appSettings>
<add key="db4oFileName" value="~/Data/Test.yap"/>
</appSettings>
Make sure that you have Data folder inside you web-site directory. ASPNET user should have enough rights to create and modify files inside this folder. You should also make sure that Data folder is not accessible to anonymous user; otherwise web-server visitors will be able to download your database.
We will open db4o connection only with the first client request:
01public static IObjectContainer Client 02
{ 03
get 04
{ 05
HttpContext context = HttpContext.Current; 06
07
IObjectContainer objectClient = context.Items[KEY_DB4O_CLIENT] as IObjectContainer; 08
09
if (objectClient == null) 10
{ 11
objectClient = Server.OpenClient(); 12
context.Items[KEY_DB4O_CLIENT] = objectClient; 13
} 14
15
return objectClient; 16
} 17
}
01private static IObjectServer Server 02
{ 03
get 04
{ 05
HttpContext context = HttpContext.Current; 06
07
if (objectServer == null) 08
{ 09
string yapFilePath = context.Server.MapPath(ConfigurationSettings.AppSettings[KEY_DB4O_FILE_NAME]); 10
11
objectServer = Db4oFactory.OpenServer(yapFilePath, 0); 12
} 13
14
return objectServer; 15
} 16
}
01Public Shared ReadOnly Property Client() As IObjectContainer 02
Get 03
Dim context As HttpContext = HttpContext.Current 04
Dim objectClient As IObjectContainer = TryCast(context.Items(KEY_DB4O_CLIENT), IObjectContainer) 05
If objectClient Is Nothing Then 06
objectClient = Server.OpenClient 07
context.Items(KEY_DB4O_CLIENT) = objectClient 08
End If 09
Return objectClient 10
End Get 11
End Property
01Private Shared ReadOnly Property Server() As IObjectServer 02
Get 03
Dim context As HttpContext = HttpContext.Current 04
If objectServer Is Nothing Then 05
Dim yapFilePath As String = context.Server.MapPath(ConfigurationManager.AppSettings(KEY_DB4O_FILE_NAME)) 06
objectServer = Db4oFactory.OpenServer(yapFilePath, 0) 07
End If 08
Return objectServer 09
End Get 10
End Property
The following code will ensure that the database is closed upon termination:
01private void Application_EndRequest(object sender, EventArgs e) 02
{ 03
HttpApplication application = (HttpApplication)sender; 04
HttpContext context = application.Context; 05
06
07
IObjectContainer objectClient = context.Items[KEY_DB4O_CLIENT] as IObjectContainer; 08
09
if (objectClient != null) 10
{ 11
objectClient.Close(); 12
} 13
14
objectClient = null; 15
context.Items[KEY_DB4O_CLIENT] = null; 16
}
1public void Dispose() 2
{ 3
if (objectServer != null) 4
{ 5
objectServer.Close(); 6
} 7
8
objectServer = null; 9
}
01Private Sub Application_EndRequest(ByVal sender As Object, ByVal e As EventArgs) 02
Dim application As HttpApplication = CType(sender, HttpApplication) 03
Dim context As HttpContext = application.Context 04
Dim objectClient As IObjectContainer = TryCast(context.Items(KEY_DB4O_CLIENT), IObjectContainer) 05
If Not (objectClient Is Nothing) Then 06
objectClient.Close() 07
End If 08
objectClient = Nothing 09
context.Items(KEY_DB4O_CLIENT) = Nothing 10
End Sub
1Public Sub Dispose() Implements IHttpModule.Dispose 2
If Not (objectServer Is Nothing) Then 3
objectServer.Close() 4
End If 5
objectServer = Nothing 6
End Sub
This is basically all the functionality that is required from db4o module. In order to make use of it we need to register it in Web.Config:
<httpModules>
<add type="Db4objects.Db4odoc.Web.Data.Db4oHttpModule"
name="Db4oHttpModule" />
</httpModules>
With the help of the created module we can access db4o database fairly easy:
1public static void SaveMessage(string username, string text) 2
{ 3
Message msg = new Message(username, text); 4
Db4oHttpModule.Client.Set(msg); 5
}
1public static IList RetrieveAll() 2
{ 3
return Db4oHttpModule.Client.Get(typeof(Message)); 4
}
1public static void DeleteAll() 2
{ 3
IList messages = Db4oHttpModule.Client.Get(typeof(Message)); 4
foreach (Message msg in messages) 5
{ 6
Db4oHttpModule.Client.Delete(msg); 7
} 8
}
1Public Shared Sub SaveMessage(ByVal username As String, ByVal text As String) 2
3
Dim msg As Message = New Message(username, text) 4
Db4oHttpModule.Client.Set(msg) 5
End Sub
1Public Shared Function RetrieveAll() As IList 2
Return Db4oHttpModule.Client.Get(GetType(Message)) 3
End Function
1Public Shared Sub DeleteAll() 2
3
Dim messages As IList = Db4oHttpModule.Client.Get(GetType(Message)) 4
For Each msg As Message In messages 5
Db4oHttpModule.Client.Delete(msg) 6
Next 7
8
End Sub
To test the whole application you can use the following simple form:
01<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="Db4objects.Db4odoc.Web._Default" %> 02
03
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 04
05
<html xmlns="http://www.w3.org/1999/xhtml" > 06
<head><title>Guestbook.aspx</title></head> 07
<body> 08
09
<form id="Form1" runat="Server"> 10
<b>Username:</b> 11
<br><input id="username" type="text" size="30" runat="Server"> 12
13
<p> 14
15
<b>Message:</b> 16
<br><textarea id="message" cols=60 rows=10 runat="Server"></textarea> 17
18
<p> 19
20
<input id="BtnGet" type="submit" value="Get messages" 21
OnServerClick="ButtonGet_Click" runat="Server"> 22
23
<input id="BtnSet" type="submit" value="Add message" 24
OnServerClick="ButtonSet_Click" runat="Server"> 25
26
<input id="BtnClear" type="submit" value="Clear messages" 27
OnServerClick="ButtonClear_Click" runat="Server"> 28
29
<span id="entries" runat="Server"/> 30
31
</form> 32
33
</body> 34
</html>
01using System; 02
using System.Collections; 03
using Db4objects.Db4odoc.Web.Data; 04
05
namespace Db4objects.Db4odoc.Web 06
{ 07
08
public partial class _Default : System.Web.UI.Page 09
{ 10
protected void Page_Load(object sender, EventArgs e) 11
{ 12
13
} 14
15
public static IList RetrieveAll() 16
{ 17
return Db4oHttpModule.Client.Get(typeof(Message)); 18
} 19
// end RetrieveAll 20
21
public static void DeleteAll() 22
{ 23
IList messages = Db4oHttpModule.Client.Get(typeof(Message)); 24
foreach (Message msg in messages) 25
{ 26
Db4oHttpModule.Client.Delete(msg); 27
} 28
} 29
// end DeleteAll 30
31
public static void SaveMessage(string username, string text) 32
{ 33
Message msg = new Message(username, text); 34
Db4oHttpModule.Client.Set(msg); 35
} 36
// end SaveMessage 37
38
public void ButtonGet_Click(Object s, EventArgs e) 39
{ 40
entries.InnerHtml = ""; 41
IList list = RetrieveAll(); 42
foreach (Message msg in list) 43
{ 44
entries.InnerHtml = "<hr>" + msg.ToString() + entries.InnerHtml; 45
} 46
} 47
// end ButtonGet_Click 48
49
public void ButtonSet_Click(Object s, EventArgs e) 50
{ 51
SaveMessage(username.Value, message.Value); 52
username.Value = ""; 53
message.Value = ""; 54
} 55
// end ButtonSet_Click 56
57
public void ButtonClear_Click(Object s, EventArgs e) 58
{ 59
DeleteAll(); 60
entries.InnerHtml = ""; 61
} 62
// end ButtonClear_Click 63
} 64
}
01<%@ Page Language="VB" AutoEventWireup="true" CodeFile="Default.aspx.vb" Inherits="Db4objects.Db4odoc.Web._Default" %> 02
03
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 04
05
<html xmlns="http://www.w3.org/1999/xhtml" > 06
<head><title>Guestbook.aspx</title></head> 07
<body> 08
09
<form id="Form1" runat="Server"> 10
<b>Username:</b> 11
<br><input id="username" type="text" size="30" runat="Server"> 12
13
<p> 14
15
<b>Message:</b> 16
<br><textarea id="message" cols=60 rows=10 runat="Server"></textarea> 17
18
<p> 19
20
<input id="BtnGet" type="submit" value="Get messages" 21
OnServerClick="ButtonGet_Click" runat="Server"> 22
23
<input id="BtnSet" type="submit" value="Add message" 24
OnServerClick="ButtonSet_Click" runat="Server"> 25
26
<input id="BtnClear" type="submit" value="Clear messages" 27
OnServerClick="ButtonClear_Click" runat="Server"> 28
29
<span id="entries" runat="Server"/> 30
31
</form> 32
33
</body> 34
</html>
01Imports Db4objects.Db4o 02
Imports Db4objects.Db4odoc.Web.Data 03
04
05
Namespace Db4objects.Db4odoc.Web 06
Partial Class _Default 07
Inherits System.Web.UI.Page 08
09
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 10
11
End Sub 12
13
Public Shared Function RetrieveAll() As IList 14
Return Db4oHttpModule.Client.Get(GetType(Message)) 15
End Function 16
' end RetrieveAll 17
18
Public Shared Sub DeleteAll() 19
20
Dim messages As IList = Db4oHttpModule.Client.Get(GetType(Message)) 21
For Each msg As Message In messages 22
Db4oHttpModule.Client.Delete(msg) 23
Next 24
25
End Sub 26
' end DeleteAll 27
28
Public Shared Sub SaveMessage(ByVal username As String, ByVal text As String) 29
30
Dim msg As Message = New Message(username, text) 31
Db4oHttpModule.Client.Set(msg) 32
End Sub 33
' end SaveMessage 34
35
Public Sub ButtonGet_Click(ByVal s As Object, ByVal e As EventArgs) 36
entries.InnerHtml = "" 37
Dim list As IList = RetrieveAll() 38
For Each msg As Message In list 39
entries.InnerHtml = "<hr>" + msg.ToString() + entries.InnerHtml 40
Next 41
End Sub 42
' end ButtonGet_Click 43
44
Public Sub ButtonSet_Click(ByVal s As Object, ByVal e As EventArgs) 45
SaveMessage(username.Value, Message.Value) 46
username.Value = "" 47
Message.Value = "" 48
End Sub 49
' end ButtonSet_Click 50
51
Public Sub ButtonClear_Click(ByVal s As Object, ByVal e As EventArgs) 52
DeleteAll() 53
entries.InnerHtml = "" 54
End Sub 55
' end ButtonClear_Click 56
End Class 57
58
End Namespace
If you are creating your application in ASP.NET2 you should take into consideration the fact that the assembly names are generated automatically on each build by default. Db4o distinguish persisted classes by name, namespace and assembly, so after the assembly name change, you won't be able to access classes saved with the previous version of the assembly.
There are several workarounds:
aspnet_compiler.exe
-v /WebSite -f -fixednames c:\WebSite -c -errorstack
1public void ConfigureAlias() 2
{ 3
Assembly assembly = Assembly.GetExecutingAssembly(); 4
String assemblyName = "Db4objects.Db4odoc.Web.Data.*, " + assembly.GetName().ToString().Substring(0, assembly.GetName().ToString().LastIndexOf("Version") - 2); 5
Db4oFactory.Configure().AddAlias(new WildcardAlias("Db4objects.Db4odoc.Web.Data.*, WebSite", assemblyName)); 6
}
1Public Sub ConfigureAlias() 2
Dim asm As Assembly = Assembly.GetExecutingAssembly() 3
Dim asmName = "Db4objects.Db4odoc.Web.Data.*, " + asm.GetName().ToString().Substring(0, asm.GetName().ToString().LastIndexOf("Version") - 2) 4
Db4oFactory.Configure().AddAlias(New WildcardAlias("Db4objects.Db4odoc.Web.Data.*, WebSite", asmName)) 5
End Sub
You can use TypeAlias for aliasing only specific class.