Multiple Database Context Mess and Intercepting writes on a WCF Data Service

Hi,
Another weekend on hacking code to get the Tyrannt project off the ground. Again I am concentrating on the middle OData web service tier. One of the rules I set myself was to not allow this tier to update the database. These update requests are only meant to be done on the back end tier via messages passed along the Azure Service Bus (ASB).
After an initial hiccup which resulted in my WCF service request falling over with “Not enough memory” (These are hosted in Azure extra small compute instances). I managed to get a working service in the cloud that exposed all my current tables.
Next I wanted to split the tables over multiple data services. I initially achieved this by creating multiple database contexts. This also allowed me to intercept the SaveChanges call in the database context when someone did a Post or Put (Below is my current thinking of how to do this, although this may change when I find it doesn’t work ;-) )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Public Overrides Function SaveChanges() As Integer
    For Each change In ChangeTracker.Entries
        Dim job As tJob
        Dim entity = change.Entity
        Dim entityType = change.Entity.GetType.Name
        Select Case entityType
            Case "NewsArticle"
                job = New tjUpdateNewsArticle
                Dim na As NewsArticle = CType(entity, NewsArticle)
                '.... Etc
        End Select
    Next
 
    Return MyBase.SaveChanges()
End Function
But when it came to trying to actually run this, I kept getting an error saying:
The model backing the 'TyranntSubsetContext' context has changed since the database was created.
After a lot of searching it seemed like some people said this was possible and other said it was not. I decided to change tack and use a single database context that had all my tables in it, but make a duplicate one in my service project which I can use to intercept the saves. (The Back end tier will need normal database access as this will be doing the writes)
Anyway I still needed to expose different tables in different services. And as a nice surprise this time, it was very easy to do.
Here is my DB Context class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Imports System.Data.Entity
Imports Tyrannt.Model.Email
Imports Tyrannt.Model.News
Imports Tyrannt.Model.Errors
Imports Tyrannt.Model.Membership
Imports Tyrannt.Infrastructure.Jobs
Imports Tyrannt.Infrastructure.Jobs.News
 
Public Class GlobalDbContext
    Inherits DbContext
 
    Public Property NewsArticles As DbSet(Of NewsArticle)
    Public Property EmailMessages As DbSet(Of EmailMessage)
    Public Property ErrorMessages As DbSet(Of ErrorMessage)
    Public Property Members As DbSet(Of Member)
    Public Property MemberTypes As DbSet(Of MemberType)
 
    'Public Overrides Function SaveChanges() As Integer
    '    For Each change In ChangeTracker.Entries
    '        Dim job As tJob
    '        Dim entity = change.Entity
    '        Dim entityType = change.Entity.GetType.Name
    '        Select Case entityType
    '            Case "NewsArticle"
    '                job = New tjUpdateNewsArticle
    '                Dim na As NewsArticle = CType(entity, NewsArticle)
 
    '        End Select
    '    Next
 
    '    Return MyBase.SaveChanges()
    'End Function
 
End Class
And this is my service code (For now I only want to expose the NewsArticles one) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Imports System.Data.Services
Imports System.Data.Services.Common
Imports System.Linq
Imports System.ServiceModel.Web
 
Public Class News
    Inherits DataService(Of GlobalDbContext)
 
    ' This method is called only once to initialize service-wide policies.
    Public Shared Sub InitializeService(ByVal config As DataServiceConfiguration)
 
        ' Expose only the required tables with the relevant access rights
        config.SetEntitySetAccessRule("NewsArticles", EntitySetRights.All)
 
        ' General settings
        config.UseVerboseErrors = True
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3
    End Sub
 
End Class
And it worked :-)
For those curious, here is the service URI:
https://tyranntrpg.org:8443/OData/Codex.svc/
I cannot guarantee this service will always work or still exist in future but it’ll be there while I test client side code.
Previous
Next Post »