Embedding ObjectSpaces Mapping Info in an Assembly
ObjectSpaces needs three XML documents to completly define the mapping between persistent classes and SQL Server databases. However, keeping these mapping files separate from the application code has the drawback, that mapping info and code/class definitions can get out of sync. You need to remember to always deploy three additional files with your app's assemblies.
This problem can be solved by:
1. Defining all three mapping documents within just one XML file.
2. Embedding the one XML file into your assembly as a resource.
As a result you can focus on deploying just your assemblies and can be sure, your XML mappings are always correct.
How to integrate the OSD and RSD mappings into the MSD mapping info
In order integrate all mapping info into just one XML file you need to replace the <Schema Location="..."/> references in the MSD document with <InlineSchema> elements. Then put into these elements the XML definition from the OSD and RSD files.
MSD document referencing OSD/RSD mapping files:
<m:MappingSchema xmlns:m="http://schemas.microsoft.com/data/2002/09/28/mapping">
<m:DataSources>
<m:DataSource Name="NorthwindRSD" Type="SQL Server" Direction="Source">
<m:Schema Location="rsd.xml"/>
<m:Variable Name="Customers" Select="Customers" />
</m:DataSource>
<m:DataSource Name="DataTypesOSD" Type="Object" Direction="Target">
<m:Schema Location="osd.xml"/>
</m:DataSource>
</m:DataSources>
<m:Mappings>
...
</m:Mappings>
</m:MappingSchema>
Single MSD document with OSD/RSD mapping info:
<m:MappingSchema xmlns:m="http://schemas.microsoft.com/data/2002/09/28/mapping">
<m:DataSources>
<m:DataSource Name="NorthwindRSD" Type="SQL Server" Direction="Source">
<m:InlineSchema>
<rsd:Database Name="Northwind" Owner="sa"
xmlns:rsd="http://schemas.microsoft.com/data/2002/09/28/rsd">
<r:Schema Name="dbo"
xmlns:r="http://schemas.microsoft.com/data/2002/09/28/rsd">
...
</r:Schema>
</rsd:Database>
</m:InlineSchema>
<m:Variable Name="Customers" Select="Customers" />
</m:DataSource>
<m:DataSource Name="DataTypesOSD" Type="Object" Direction="Target">
<m:InlineSchema>
<osd:ExtendedObjectSchema Name="DataTypesOSD"
xmlns:osd="http://schemas.microsoft.com/data/2002/09/20/persistenceschema">
<osd:Classes>
...
</osd:Classes>
</osd:ExtendedObjectSchema>
</m:InlineSchema>
</m:DataSource>
</m:DataSources>
<m:Mappings>
...
</m:Mappings>
</m:MappingSchema>
How to embed a single MSD file into an assembly
Embedding the single MSD file, e.g. msdAll.xml, into an assembly is easy. Just call the Add Existing Item menu item on the project, add the file, and then set the Build Action file property to "Embedded Resource". When you compile the project, the file gets embedded into the assembly. Its name is the file name prefixed with the assemblies root namespace.
How to load the MSD document from an embedded resource
To load the MSD resource, you need to open a stream on the embedded file using GetManifestResourceStream() of its assembly. Don´t forget to fully qualify the resource name with its namespace!
Then you open a XmlTextReader on the resource stream.
However, due to an error in the current .NET Fx 2.0 version you can´t just write new XmlTextReader(myResourceStream), but have to pass in also a URL. Any URL/filename will do.
After that, you load the MSD mapping info into a MappingSchema instance which you pass to the ObjectSpace constructor.
That´s it.
Here´s an example:
Imports System.Data.SqlClient
Imports System.Data.ObjectSpaces
Imports System.Data.sqlxml
Imports System.Data.Mapping
Module Module1
Sub Main()
Dim conn As New SqlConnection("server=localhost;integrated security=true;database=northwind")
Dim s As IO.Stream
s = System.Reflection.Assembly.GetExecutingAssembly.GetManifestResourceStream("ConsoleApplication1.msdAll.xml")
Dim rd As New System.Xml.XmlTextReader("msdAll.xml", s)
Dim msd As New MappingSchema(rd)
Dim os As New ObjectSpace(msd, conn)
End Sub
End Module
Thanks to Jeff Reed from Microsoft for his help.