Wednesday, 14 May 2008

Introducing LinqToDbmlRunner

I've created a tool based on my previous post. This should allow scripting of dbml changes in a team environment.

The project is hosted at http://code.google.com/p/linqtodbmlrunner/ Enjoy!

Monday, 12 May 2008

Scripting changes to Linq To SQL DBML files

I've been playing with Linq To SQL and have been getting very bothered by the method MS expect us to use to develop the mappings. You can't regenerate your dbml schema without overwriting the changes you made in the designer. Not only this, but your changes won't merge well with changes made by other developers on your team when it comes to check-in time as they are all in xml files.

The process that is required for safe, team development that I've come up with is this:

1. Update database schema (using something like migratordotnet) 2. Generate just the dbml file from schema using sqlmetal.exe 3. Run a change script of some kind against the dbml file to update it to include your custom mappings. 4. Generate the classes from the dbml file using sqlmetal.exe

Step 3 is the missing link. You could use xslt, xpath or Linq to XML. You could even generate change scripts using the designer and MS XML Diff. But the easiest thing to use is a Linq To XSD program and put it in the post build events for a project that contains the generated XSD file as an embedded resource. Linq To XSD gives you typed control over the dbml file in C#.

This lets you write something like this in your script:

var dbml = XRoot.Load(@"..\..\GdwDb.dbml");
foreach (var table in dbml.Database.Table)
{
foreach (var column in table.Type.Column.Where(c => Char.IsLower(c.Name[0]))
{
column.Name = column.Name.ToUpper()[0] + column.Name.Substring(1);
}
}
dbml.Save(@"..\..\GdwDb.dbml");

This snippet will update all camelCase field names to PascalCase ones. Of course you can do anything, like creating inheritance mappings, removing prefixes etc. One you write a couple of helper methods you should be away.

I would have thought a similar process could be used for NHibernate and Entity Framework, although I know some people prefer to work backwards from code to database.

You can download the latest version of Linq To XSD from here and download the Linq classes I generated for the Dbml xsd here. Include that in a project with a reference to Microsoft.Xml.Schema.Linq.DLL and you can create your own mapping update script.

Info on using SqlMetal to generate the dbml file, and the appropriate classes can be found on Ben Hall's blog here.

I'll upload a demo project later, as this could all be a little confusing.

Tuesday, 6 May 2008

Storing ViewState in memcached part 2

If you have access to the source code of the web app, you can also create inherit from Page and add the following two methods. I prefer the HttpModule myself, but this is pretty convenient. You'll still need to set up the memcached settings in web.config protected override void SavePageStateToPersistenceMedium(object state) { var key = Guid.NewGuid().ToString(); BeIT.MemCached.MemcachedClient.GetInstance("ViewStateCache").Add(key, state); base.SavePageStateToPersistenceMedium(new Pair("Key", key)); } protected override object LoadPageStateFromPersistenceMedium() { var pair = (Pair)base.LoadPageStateFromPersistenceMedium(); return BeIT.MemCached.MemcachedClient.GetInstance("ViewStateCache").Add(key, pair.Second); }

Sunday, 4 May 2008

Storing ASP.NET ViewState in memcached

This has been deprecated! Please see this post After reading various old blog posts about moving the ViewState to the end of the page using an HttpModule, I decided to create an HttpModule to store the ViewState in memcached, eliminating the need to send the data back and forth to the client and stopping prying eyes from seeing the ViewState. Halfway through writing the HttpModule, I discovered that Philip Rieck had already written a pluggable ViewState manipulation HttpModule, so I made a memcached plugin for it using the BeITMemcached client. To get this up and running on your site, download the latest source from http://code.google.com/p/memcachedviewstatehttpmodule/ and follow these steps 1. Copy all the code from the Release folder into your web sites bin directory 2. Merge the xml below into your web.config and edit the memcached server addresses <configuration> <configSections> <section name="beitmemcached" type="System.Configuration.NameValueSectionHandler" /> </configSections> <appSettings> <add key="viewRestateStore" value="Assembly"/> <add key="viewRestateStoreType" value="MemcachedViewStateStore.MemcachedViewStateStore,MemcachedViewStateStore"/> </appSettings> <beitmemcached> <add key="ViewStateCache" value="127.0.0.1" /> </beitmemcached> <system.web> <httpModules> <add name="viewrestate" type="NFission.Web.ViewRestateModule,NFission.Web.ViewRestate"/> </httpModules> </system.web> </configuration> 3. That should be it. A couple of words of warning. I haven't used this in production yet, but will hopefully do so sometime in the next week. Also, I haven't distibuted the source for Philip Riecks HttpModule as I don't know the licence for it. I had to make a couple of minor changes to get it to work correctly
  • I commented out the GZip stuff as I'm not using it
  • changed line 72 of VsInFilter from Buffer.BlockCopy( this.dataBuffer, (int)position, buffer, offset, count); to Buffer.BlockCopy( this.dataBuffer, (int)position, buffer, offset, realCount);).
  • changed line 16 of VsFilter from private const string ViewstateKey = "name=\"__VIEWSTATE\ value=\"";" to private const string ViewstateKey = "id=\"__VIEWSTATE\" value=\"";

I'm trying to get in touch with Philip to clear up the licence.