Using a Database
Using a database to hold resources is a key feature of the Resource Application Block and turns resource management into an enterprise feature. The Resource Application Block, however, is a provider model for getting at resources from various different resource storage types and is thus not really responsible for getting the resources there in the first place. Having said that the provider model would not be complete unless there was some form of support for editing those resources. For this reason every resource provider type has been coded with an associated
IResourceWriter to support resource editing of the resource storage type.
Using the
Data Resource Provider requires a little more effort to setup than any of the other provider types.
Creating a Resource Database
Provided with the source code is a SQL script to create a
Resource database (
CreateResourceDatabase.sql) and a console command to run the script (
CreateResourceDb.cmd). The command and script assume that Microsoft SQL Server is the database type and the script must be run on the machine that has SQL Server installed. The syntax of the console command is:
[Command Console]
C:\>CreateResourceDb.cmd SQLEXPRESS
Note: the parameter applied to the command, this represents the
instance name of the installation of SQL Server that you want to use. If you are using the
default instance then leave this parameter blank.
The
authentication model that you wish to use is left up to you. Now you need to configure the database using the
Data Access Application Block. This block is added automatically in the Configuration Console as soon as you select the
DataResourceProvider. Configure an appropriate
ConnectionString to get at the database. See
Configuration for more detail.
Adding and Editing Resources in the Database
This is done using the
DataResourceWriter which implements the standard .NET Framework
IResourceWriter interface. This means that it will work with any open source or commercially available resource editor. The Resource Application Block itself does not provide a resource editor of its own and I have a mind to provide one in a later release, or more probably, write an API to use the one that Guy Smith-Ferrier has provided with his book
.NET Internationalization.
If you wish to use the resource writer in your code then the following code sample might help:
[C#]
// use the Data Access Application Block to create your database instance using the configured connection string, "ResourceDatabase" in this example
Database database = DatabaseFactory.CreateDatabase("ResourceDatabase");
// create a DataResourceWriter to use to write resources to this database, notice we are using the invariant (or neutral) culture
// and grouping the set of resources together with the base name of "MyResources"
DataResourceWriter dataResourceWriter = new DataResourceWriter(database, "MyResources", CultureInfo.InvariantCulture);
// the following code lines show how a variety of resource data types can be written to the database
// adding a string
dataResourceWriter.AddResource("TestString", "This is a string");
// adding an integer
int testInt = 27;
dataResourceWriter.AddResource("TestInteger", testInt);
// adding an icon
Icon testIcon = new Icon("C:\testicon.ico");
dataResourceWriter.AddResource("TestIcon", testIcon);
// adding an image
Bitmap testImage = new Bitmap("C:\testImage.bmp");
dataResourceWriter.AddResource("TestImage", testImage);
// adding an audio resource (or any BLOB for that matter)
FileInfo fi = new FileInfo("C:\audio.wav");
FileStream fs = fi.Open(FileMode.Open);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, (int)fs.Length);
dataResourceWriter.AddResource("TestSound", buffer);
// adding a Color object
dataResourceWriter.AddResource("TestColour", Color.Red);
// adding a Comment with a resource
ResourceDataNode resourceDataNode1 = new ResourceDataNode("TestString2", "This is a string value");
resourceDataNode1.Comment = "This is a comment to go with the resource TestString2";
dataResourceWriter.AddResource(resourceDataNode1.Name, resourceDataNode1);
// adding a file reference resource, this is a reference to a file rather than the file itself
ResourceFileRef resourceFileRef = new ResourceFileRef("test.bmp", typeof(Bitmap).AssemblyQualifiedName);
ResourceDataNode resourceDataNode2 = new ResourceDataNode("TestFileRef", resourceFileRef);
dataResourceWriter.AddResource(resourceDataNode2.Name, resourceDataNode2);
dataResourceWriter.Close();
// adding generic french resources
dataResourceWriter = new DataResourceWriter(database, "MyResources", new CultureInfo("fr"));
dataResourceWriter.AddResource("TestString", "Bonjour tout le monde");
dataResourceWriter.AddResource("TestInteger", 33);
dataResourceWriter.Close();
Getting at Database Resources
This is very easy and is nothing special at all, simply use the
DataResourceProvider in the same fashion as you would for any other resource provider type.
Note: the base name is used to segregate resources into sets so that you don't need to read all the resources from the database each time.
Using Other Database Types
The above should work fairly seamlessly with
Oracle databases. For other database types there are a few caveats to what you can configure from the Data Access Application Block.
- the DataResourceProvider uses stored procedures so your database type must be able to support store procedures.
- the table uses an auto-incrementing identifier for its primary key so your database must support an auto-increment feature, However, the ID column is not actually used so it is possible to simply remove the ID column altogether.
- resource values are stored in an image data type, or any type that can hold a binary serialized byte array. If your database type cannot support BLOB's then it cannot be used.
Don't forget if any of the caveats affects your choice you have the
source code for the supplied DataResourceProvider so that you could always write your own, then use the
CustomResourceProvider to configure it.
The Resource Table
The
Resource table has the following columns:
[SQL]
CREATE TABLE [dbo].[Resources](
[ID] [int] IDENTITY(1,1) NOT NULL,
[BaseName] [varchar](250) NOT NULL,
[Culture] [varchar](10) NOT NULL,
[Name] [varchar](250) NOT NULL,
[Type] [varchar](250) NULL,
[MimeType] [varchar](250) NULL,
[Value] [image] NULL,
[Comment] [nvarchar](max) NULL,
CONSTRAINT [PK_Resources] PRIMARY KEY NONCLUSTERED ([ID] ASC)
WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY]