July 2009 - Posts
Today I tried to write my first unit tests under Visual Studio 2010. Just to see if Visual Studio testing system can now also be used for unit tests. Visual Studio 2008 had some annoying problems with test and I preferred to use nUnit instead. Visual Studio 2010 brings some good news – tests work. Take a look at my example.
Problems with tests under Visual Studio 2008
Visual Studio 2008 tests are problematic because they are not able to handle System.Exception as expected exception. Okay, I know the background, System.SystemException should be base class for fatal system exceptions and System.ApplicationException should be base class for non-fatal application exceptions. But this works only somewhere we don’t belong – the ideal world. Applications still throw System.Exception and also .Net Framework classes throw it.
Here is example of failing test. Notice that ExpectedException sais that System.Exception is expected when test is run.
[TestMethod]
[ExpectedException(typeof(Exception))]
public void ThisTestFails()
{
throw new Exception("This test fails!");
}
And here you can see the result.
Test fails with error message: UTA017: TestProject1.UnitTest1.ThisTestFails has invalid ExpectedException attribute. The type must inherit from Exception. I handle this situation as bug in Visual Studio because this limitation is pointless – System.Exception is not abstract class.
Every bad thing usually has its good side too. Under these limited conditions one can avoid the amount of hack-tests low by throwing correct exceptions in his or her code. If something is null that should have value then instead of System.Exception it is good idea to throw System.ArgumentNullException etc.
Visual Studio 2008 tests hack
There are two hacks to solve this issue. First hack has same structure as code above. We just change the type of exception we expect and in test we throw exception using correct type.
[TestMethod]
[ExpectedException(typeof(ApplicationException))]
public void ThisTestChangesExceptionType()
{
try
{
throw new Exception("This test passes!");
}
catch (Exception ex)
{
throw new ApplicationException(ex.Message, ex);
}
}
Our second hack is simpler. Instead of using ExpectedException attribute we assert the type of exception.
[TestMethod]
public void ThisTestUsesAssert()
{
try
{
throw new Exception("This test passes!");
}
catch (Exception ex)
{
Assert.IsTrue(ex.GetType() == typeof(Exception));
}
}
Now we get nice output for these tests as shown on following screenshot.
Both versions of this test passed well. Although these solutions are not very nice they work.
Visual Studio 2010 tests
Visual Studio 2010 handles the first test correctly. Here is the code of my test.
[TestMethod]
[ExpectedException(typeof(Exception))]
public void ThisTestExpectsException()
{
throw new Exception("Visual Studio 2010 rocks!");
}
And here is the screenshot with test result.

As we can see Visual Studio 2010 has this issue fixed and we can write also tests that expect System.Exception to be thrown. Happy testing!
Analysis Patterns: Reusable Object Models is another create patterns book by
Martin Fowler. The audience of this book are analysts whose work is analysis of information systems and modeling data structures. This book is also recommended reading for programmers and software designers.
For me those models were pretty abstract but they are not hard to understand. If reader has some experiences on data modeling then her or she may find here a lot of good ideas and points. I think I am much more smarter next time when I start modeling some financial or other complex system. Of course, this book is also useful for smaller systems because good analysis almost guarantees that system works by its internal logic as users expect.
I got also some ideas about things that exist in almost every information system (classificators by example). hPatterns in the book pretty fundamental and it is not hard to use them in different contexts. There are also some examples about it in the book.
I consider this book as another great and timeless investment, just like Data Model Resource Books are.
Cite from Amazon
Patterns are higher-order designs that can be reused across projects and types of computer systems. Analysis Patterns: Reusable Object Models defines over 70 patterns, beginning with some from the business world, such as the Party and Accountability patterns, which define the players in organizations and whom they report to. Many of the other patterns are drawn from the health care industry and mainly show patterns of doctor-patient interactions.
Table of Contents
1. Introduction
I ANALYSIS PATTERNS
2. Accountability
3. Observations and Measurements
4. Observations for Corporate Finance
5. Referring to Objects
6. Inventory and Accounting
7. Using the Accounting Models
8. Planning
9. Trading
10. Derivative Contracts
11. Trading Packages
II SUPPORT PATTERNS
12. Layered Architecture for Information Systems
13. Application Facades
14. Patterns for Type Model Design Templates
15. Association Patterns
16. Afterword
APPENDIX
A. Techniques and Notations
B. Table of Patterns
I have custom authentication and user profiles solution where user profiles are stored in list. This list is directly accessible only to administrators. Users can register to site and modify their profiles through special pages that run profile operations under elevated privileges. Users have three versions of their avatar: 64x64, 32x32 and 16x16. These avatars are saved as user profile attachments when user uploads his or her avatar. Because avatars are used at almost every page in portal I wrote IHttpHandler that provides avatars based on user profile ID.
Here is shortened draft version of my code (I removed some complex guard checks that use custom extensions methods for SharePoint objects).
public class ProfileImageHandler : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
var request = context.Request;
var response = context.Response;
var idString = request.QueryString["id"];
var sizeString = request.QueryString["size"];
var id = 0;
int.TryParse(idString, out id);
var siteId = SPContext.Current.Site.ID;
var sec = new SPSecurity.CodeToRunElevated(delegate()
{
using (var site = new SPSite(siteId))
{
using (var web = site.OpenWeb())
{
if (id == 0)
{
OutputDefaultImage(web, response);
response.End();
return;
}
var list = web.Lists["ProfileList"];
var item = list.GetItemById(id);
sizeString = sizeString + "x" + sizeString;
foreach (string fileName in item.Attachments)
{
if (!fileName.Contains(sizeString))
continue;
var fileUrl = item.Attachments.UrlPrefix + fileName;
var file = web.GetFile(fileUrl);
var stream = file.OpenBinaryStream();
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
response.Clear();
response.ContentType = "image/png";
response.BinaryWrite(bytes);
stream.Dispose();
response.End();
}
}
}
}
);
SPSecurity.RunWithElevatedPrivileges(sec);
}
private void OutputDefaultImage(SPWeb web, HttpResponse response)
{
var defaultFileUrl = "/Style Library/portal/images/user.gif";
var defaultFile = web.GetFile(defaultFileUrl);
var defaultFileStream = defaultFile.OpenBinaryStream();
var defaultBytes = new byte[defaultFileStream.Length];
defaultFileStream.Read(defaultBytes, 0, defaultBytes.Length);
response.Clear();
response.ContentType = "image/png";
response.BinaryWrite(defaultBytes);
defaultFileStream.Dispose();
}
}
The code here works as follows. It retrieves user profile by id and checks if profile has image with given width and height. Avatars in this system are squares so I need to know only size of one side. If user profile doesn’t have attachment that contains size x size (by example “32x32”) in its name then default profile image is returned.
Let’s suppose we have user profile (id = 176) and we want 32x32 size avatar for this profile. Also let’s assume there is userimagehandler.ashx file in the folder portalhandlers. We can ask 32x32 avatar by using the following request.
/_layouts/portalhandlers/userimagehandler.ashx?size=32&id=176
As URL for each avatar size is unique for each profile then it is also possible to cache avatars so there is no need to read them from content database per every request.
Entity Framework 4.0 is able to generate database schema based on model. If you built your model first and you now want to create database for it you can use new Generate Database Script from Model feature. Let’s see how it works.
I will use my example gallery model. Let’s assume we have model opened in Visual Studio 2010.
- Click right mouse button on model and select Generate Database from Model, as shown on picture below.

- Specify database connection and click Next.

- Copy generated SQL script to SQL Server Management Studio and run it.

When you decide to save changes when clicking on Finish button then the following happens (taken from Gil Fink blog posting Model First in Entity Framework 4):
- new store schema definition (SSDL) will be generated,
- new mapping specification (MSL) will be generated,
- EDMX file will be updated using previously generated SSDL and MSL,
- script with SQL will be saved to location you show,
- new connection definition will be added to application configuration file.
I found some issues with POCOs I use (read more from my blog entry Entity Framework 4.0: How to use POCOs):
- table names are not correct: instead of gallery_item, album and photo I got gallery_item, gallery_item_Album and gallery_item_Photo as result,
- no primary keys were generated,
- no foreign keys were generated.
It is possible that this is limitation of Entity Framework 4.0 because it is still in beta. But it may also be some hard-to-trace problem deep inside my model definition. I will update this posting as soon as I find out why I got those problems with POCOs.
2009-08-07 Update I got the following very promising answer from Microsoft Connect to my question:
Thank you for your feedback. At this point in time we are not able to make significant changes to the system. So instead, I will explain what is going on. Specifically, in response to this part of the bug filing:
"One thing that occurs always is problem related to table names - they are incorrect in generated SQL. Example is here:
1) Correct: album, Generated: gallery_item_Album
2) Correct: photo, Generated: gallery_item_Photo"
What happens here is that we take the name of the set associated with the root type in your hierarchy, in this case "gallery_item", and we prepend it to the name of the type.
The idea was (and it may not have been right, but it is what we have now) is to communicate what is actually happening. In this case, the "gallery_item_Album" table holds all members of the "gallery_item" set that are of type Album. So if you rename your set to, for example "GalleryItems" then you will get three tables:
GalleryItems,
GalleryItems_Album
GalleryItems_Photo
All instances of Photo are created by joining GalleryItems with GalleryItems_Photo.
Note that you can always write your own strategy or download someone else Database Script Generation Workflow file. We, and others, are working on other workflows that will, for example, generate a single table for all members of a set, which obviates this problem. For now, this behavior is most likely what will be shipped.
So, guys, cool things are coming, we just have to wait a little bit :)
In one of my ASP.NET MVC applications I needed flexible interface for inserting invoice lines. Sometimes invoice lines are inserted in incorrect order and it saves accountants some time if they are able to change the order of invoice lines quickly. In my application I used jqGrid with TableDND extension. Here’s how I got it work.
In the end of this posting I will provide you also links so you get all the required stuff and guiding materials to get started with jQuery and jqGrid in ASP.NET.
Invoice lines
As first thing let’s see invoice line class and example screenshot. The class given here is simple toy to illustrate row reordering and not to go deep to invoice line modeling and implementation questions. Let’s start with screenshot.

And here is my simple InvoiceLine class that contains no complex business logic.
public class InvoiceLine
{
public virtual int Id { get; set; }
public virtual decimal Amount { get; set; }
public virtual string Description { get; set; }
public virtual decimal DiscountPercent { get; set; }
public virtual decimal DiscountSum { get; set; }
public virtual int LineNo { get; set; }
public virtual Invoice ParentInvoice { get; set; }
public virtual string Text { get; set; }
public virtual string Unit { get; set; }
public virtual decimal UnitPrice { get; set; }
public virtual decimal VatPercent { get; set; }
public virtual decimal Sum
{
get
{
return Amount*UnitPrice*(1 + VatPercent/100);
}
}
}
Grid
Here is the definition of my grid (it is defined in invoices detail view). Who is not familiar with selectors stuff and AJAX I give a little explanation. First block, HTML with divs, defines table where data is show and pager. JavaScrtipt below attaches jqGrid to table and pager and defines some properties and functions. When grid is created it makes request to /accounting/invoice/INVOICE_ID/lines to get invoice lines in JSON format.
<div>
<table id="list" class="scroll"></table>
<div id="pager" class="scroll"></div>
</div>
<script type="text/javascript">
$(document).ready(function() {
jQuery("#list").jqGrid({
url: '/accounting/invoice/<%= Model.Invoice.Id %>/lines',
datatype: 'json',
mtype: 'GET',
colNames: ['Id', 'No', 'Text', 'Amount', 'Unit', 'Unit Price',
'VAT %', 'Discount %', 'Discount Sum','Sum'],
colModel: [
{ name: 'Id', index: 'Id', editable: true,
width: 40, align: 'left' },
{ name: 'No', index: 'No', editable: true,
width: 40, align: 'left' },
{ name: 'Text', index: 'Text', editable: true,
width: 350, align: 'left' },
{ name: 'Amount', index: 'Amount', editable: true,
width: 50, align: 'left' },
{ name: 'Unit', index: 'Unit', editable: true,
width: 50, align: 'left' },
{ name: 'Unit Price', index: 'UnitPrice', editable: true,
width: 120, align: 'left' },
{ name: 'VAT %', index: 'VATPercent', editable: true,
width: 60, align: 'left' },
{ name: 'Discount %', index: 'DiscountPercent',
editable: true, width: 80, align: 'left' },
{ name: 'Discount Sum', index: 'DiscountSum', editable: true,
width: 80, align: 'left' },
{ name: 'Sum', index: 'Sum', editable: true, width: 80,
align: 'left' }
],
pager: jQuery('#pager'),
rowNum: 10,
rowList: [5, 10, 20, 50],
sortname: 'Id',
sortorder: "desc",
viewrecords: true,
imgpath: '/scripts/themes/steel/images',
caption: 'Invoice Lines',
editurl: '/accounting/invoice/<%= Model.Invoice.Id %>/save',
gridComplete: function() {
jQuery("#list").tableDnDUpdate();
}
}).navGrid('#pager',
{ view: false, search: false, refresh: false }, //options
{}, // edit options
{}, // add options
{}, // del options
{} // search options
);
});
</script>
Invoice lines grid gets its data from InvoiceController. This is my MVC controller that provides actions for invoices. Here is the controller action InvoiceLines that returns invoice lines to invoice detail view. This method is for the same request that jqGrid makes to get data. The code here is not nice one but it works.
public ActionResult InvoiceLines(int id)
{
var repository = Resolver.Resolve<IInvoiceRepository>();
var invoice = repository.GetById(id);
var lines = invoice.Lines;
if(lines == null)
lines = new List<InvoiceLine>();
var rowArray = new object[lines.Count];
var i = 0;
foreach (var line in lines)
{
i++;
var values = new[] {
line.Id.ToString(),
line.LineNo.ToString(),
line.Text,
line.Amount.ToString("0.00"),
"h",
line.UnitPrice.ToString("c"),
"20",
"0",
"0",
line.Sum.ToString("c")
};
var row = new { id = i, cell = values };
rowArray[i - 1] = row;
}
var jsonData = new
{
total = 1,
page = 1,
records = 3,
rows = rowArray
};
return Json(jsonData);
}
Adding support for lines reordering
You saw some code that is behind this nice invoice lines grid. Let’s add now lines reordering functionality. We use TableDND extension for jqGrid. It is possible that this extension is not included in jquery.jqGrid.js file by default. It it is not there just add this line to this file (same place where other extensions are defined):
{ include: true, incfile: 'jquery.tablednd.js', minfile: 'min/grid.tablednd-min.js' }
Now let’s go back to our invoice details view. Now we add the following javaScript to $(document).ready function, right before jQuery("#list").jqGrid() call.
jQuery("#list").tableDnD({
onDrop: function(table, row) {
var oldIndex = row.id;
var newIndex = row.rowIndex;
if (oldIndex == newIndex)
return;
$.post('/accounting/invoice/<%= Model.Invoice.Id %>/changeroworder',
{
oldPosition: oldIndex,
newPosition: newIndex
},
function(result) {
$("#list").trigger("reloadGrid");
});
}
});
Here we are doing some little mystery. We define onDrop function that is triggered when row is dropped. In this function we control if row was moved and if it is we send this information to server. In server we have controller action that takes old and new positions of row and reorders invoice lines.
Last piece of code is function that checks the results of controller action call. This way or other we have to reload rows to get same state as in server. Of course, we can optimize our code and avoid another request by controlling the returned result. If it is okay then we can change line numbers on client side.
Controller action that reorders invoice lines is as follows.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ChangeRowOrder(int invoiceId, int oldPosition, int newPosition)
{
var repository = Resolver.Resolve<IInvoiceRepository>();
repository.ChangeLineOrder(invoiceId, oldPosition, newPosition);
Response.Write("OK");
return null;
}
And here is invoice repository ChangeLineOrder() method.
public void ChangeLineOrder(int oldPosition, int newPosition)
{
var invoice = GetById(1); // changedLine.ParentInvoice;
var moveUp = (newPosition < oldPosition);
var transaction = _session.BeginTransaction();
foreach (var line in invoice.Lines)
{
if(line.LineNo == oldPosition)
{
line.LineNo = newPosition;
continue;
}
if (moveUp)
if (line.LineNo < newPosition || line.LineNo > oldPosition)
continue;
else
line.LineNo++;
else
if (line.LineNo > newPosition || line.LineNo < oldPosition)
continue;
else
line.LineNo--;
}
Save(invoice);
transaction.Commit();
}
So, that’s it guys. You can change the order of invoice lines by mouse now and new numbers are assigned to invoice lines behind the curtains. For me, the most valuable part here is the last method that reorders invoice lines. All that is above it was pretty simple to get work.
Links
I needed to attach SQL Server 2008 database to server. There was no log file, just mdf. I don’t know why but it is not very easy to get this database online. After some digging in internet I found solution.
I suggest you to read and try out example by Paul S. Randal TechEd Demo: Creating, detaching, re-attaching, and fixing a suspect database. I also suggest you to bookmark this posting, you never know…. I found simplest solution from stackoverflow: How to recover database from MDF in SQL Server 2005? It works also for SQL Server 2008.
- Create database with same name as MDF file you have.
- Stop SQL Server and swap MDF files. Make sure you also keep new database you just created.
- Start SQL Server. Database will be now in suspect state because log file is not correct.
- Run the following script:
USE [master]
GO
ALTER DATABASE [MyDatabase] SET EMERGENCY
GO
ALTER DATABASE [MyDatabase] SET SINGLE_USER
GO
DBCC CHECKDB ([MyDatabase], REPAIR_ALLOW_DATA_LOSS)
GO
ALTER DATABASE [MyDatabase] SET MULTI_USER
GO
ALTER DATABASE [MyDatabase] SET ONLINE
GO
When I ran this script I got the following output.
Msg 5173, Level 16, State 1, Line 1
One or more files do not match the primary file of the database. If you are attempting to attach a database, retry the operation with the correct files. If this is an existing database, the file may be corrupted and should be restored from a backup.
Log file 'c:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS2008\MSSQL\DATA\MyDatabase_log.ldf' does not match the primary file. It may be from a different database or the log may have been rebuilt previously.
Warning: The log for database 'MyDatabase' has been rebuilt. Transactional consistency has been lost. The RESTORE chain was broken, and the server no longer has context on the previous log files, so you will need to know what they were. You should run DBCC CHECKDB to validate physical consistency. The database has been put in dbo-only mode. When you are ready to make the database available for use, you will need to reset database options and delete any extra log files.
DBCC results for 'MyDatabase'.
Service Broker Msg 9675, State 1: Message Types analyzed: 14.
Service Broker Msg 9676, State 1: Service Contracts analyzed: 6.
Service Broker Msg 9667, State 1: Services analyzed: 3.
Service Broker Msg 9668, State 1: Service Queues analyzed: 3.
Service Broker Msg 9669, State 1: Conversation Endpoints analyzed: 0.
Service Broker Msg 9674, State 1: Conversation Groups analyzed: 0.
Service Broker Msg 9670, State 1: Remote Service Bindings analyzed: 0.
Service Broker Msg 9605, State 1: Conversation Priorities analyzed: 0.
… Long list of GBCC messages …
CHECKDB found 0 allocation errors and 0 consistency errors in database 'MyDatabase'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
You can see the error message in the output but that was no problem after all. My database is now online and works as expected.
To try out Visual Studio 2010 and .Net Framework 4.0 I decided to write simple gallery application based on ASP.NET MVC Framework. In this posting I show you my very first layouts I created for gallery. These layouts are modifications of ASP.NET MVC default blue-white-black layouts. I also added some photos of my first layout drafts. My question is – what do you think about my first draft-level layouts (I am not designer)?
First drafts
I start with to photos to show you how I started with my layouts. Usually I use retro tools for drafting – pen and paper. Here are two examples.
| |
Layout for gallery items listing. Click on image to enlarge. | Layout for photos. Click on image to enlarge. |
These drafts show no complete layout but they give direction. I know that something like this will be the final result. Of course it is possible that something changes and these drafts just illustrate only my first thoughts.
First layouts
Here are my first layouts that work already with code. I added some sample content so I can see how my gallery looks with content in it. It is good idea because trusting layouts with photo placeholders is dangerous – placeholders are usually just gray squares and photos are colored squares. Although the layout with placeholders may look nice it may be not so nice with real content.
Also notice that these layouts are first ones – don’t expect that they are 100% done, far from this. I just try to show my idea.
Gallery items listing
This is gallery items listing. Listings of albums, sub-albums and albums contents are shown as 4x3 squared layout. Currently I have no good idea how to distinguish albums and photos but there is something in my mind.

Layout for gallery items listing.
Click on image to enlarge.
To keep layout always 4x3 I am using placeholders with question mark for empty cells in gallery items table. Okay, it is not table exactly – it is div based layout. :)
Photo view
This is the view for photos. I tried photos with smaller and bigger dimensions but this one works best for me. In the future I plan to show there also a table with EXIF information and other attributes. Currently my model has no support for attributes and that’s why I have no attributes on this layout.

Photo view layout.
Click on image to enlarge.
I plan to add here selection for multiple sizes like 800x600, 1024x704 and original size. The other thing I plan here is Add to Basket button so visitor can make his/her own selection of photos and download these as zip-file.
Questions to You
You saw here some layouts of my photo gallery application. My questions are:
- what do you think about my current layouts?
- do you notice inconveniences there?
- what I should change to make my layouts better?
- do you have any other suggestions?
Thanks for everybody who has time two answer. :)
My Windows 7 Beta is expired. After about two hours of work computer restarts. During restart it shows me the following BSOD.
As you can see then Windows 7 has also constant for the end of evaluation period defined. :)
In my last posting about Entity Framework 4.0, Entity Framework 4.0: POCOs and table-per-type inheritance mapping, I made first generalization to my photo gallery model. I introduced GalleryItem class that is base class for all that can be added to gallery: new albums, photos and maybe videos too. Although everything works as expected my model needs some modifications because it is not very foolproof.
Analyzing current model
Let’s take a look at current model. Currently album is self-referencing class. It was okay because albums may have sub-albums. Also albums my contain photos and we had also association from Album to Photo.
But there are some nasty side effects:
- Album contains direct association to Photos. When we add new class for videos then we must add new association to Album class. All queries for Album children go more complex because we have to query ChildAlbums, Photos and Videos. Think about gallery items view where nine items from current album are shown ordered by date.
- Adding new classes to model that extend GalleryItem mean that we have two database relations per table: one from GalleryItem to new table and one from Album to new table.
Somehow we have to protect Album class so it doesn’t grow as new descendant is added for GalleryItem.
Solution
To solve our problem we need some modifications. We will move ParentAlbum property from Album class to GalleryItem class. This guarantees that every item in gallery may have parent album. If we have new class called Video that extends GalleryItem then Video gets parent album automatically.

As you can see from new model diagram then we don’t need association from Album to Photo anymore. We can easily add new classes that extend GalleryItem and we don’t have to change other classes. Also all classed based on GalleryItem have ParentAlbum property.
On Entity Framework 4.0 everything works fine. I changed my classes and my mappings a little bit and everything works now as expected.
Code
So, here is the code of classes and it is exactly what I wanted.
public abstract class GalleryItem
{
public virtual int Id { get; set; }
public virtual string Description { get; set; }
public virtual GalleryItem ParentAlbum { get; set; }
public virtual string Title { get; set; }
public virtual bool Visible { get; set; }
}
public class Album : GalleryItem
{
public virtual ICollection<GalleryItem> ChildItems { get; set; }
}
public class Photo : GalleryItem
{
public virtual string FileName { get; set; }
public virtual bool IsGalleryThumb { get; set; }
}
As you can see then Album class contains now only one automatic property. Although we should be more careful here (everybody can assign new value to ChildItems collection) I don’t have problem with it right now. When I discover the problem then it is time to find a solution.
Why not composite pattern?
Reader who knows patterns can see here Composite Pattern. At least our associations are made this way but GalleryItem misses some methods. I know that and I don’t even consider using Composite Pattern here. Why? Because I really don’t need it right now.
Okay, many i-know-everything gurus, idealists and other maniacs will scream now divine revelations of dark doom of my model and my application. It is blasphemy in this point not to use Composite Pattern. If these guys knew where I live then they were considering next crusade. But don’t care about them.
This far I have used my common sense to go on step by step. I’m not swimming in safe waters and most of my work here is experimenting. That’s why I don’t put any efforts to ideal architecture and packaging right now. Also there is no point to implement any pattern just because something almost looks like following this pattern.
Of course, I don’t abandon Composite Pattern completely. I made a note to my private development Wiki that there is something very similar to Composite Pattern. That’s enough for now. As a first thing I try to use the new architecture in my code.
In my previous posting Entity Framework 4.0: How to use POCOs I introduced how simple it is to use POCOs with Entity Framework 4.0. In this posting I will refactor my photo gallery model a little bit and introduce you how to implement table-per-type inheritance mapping on Entity Framework 4.0.
Analyzing current model
Let’s start with analyzing the current model shown below. We can see that Album and Photo have some fields in common: Id, Title, Description and Visible. Currently these fields are duplicated to both tables.
Photo Gallery. This is my current very simple model. I made this model so trivial
because it is easier to study new code stuff step-by-step.
I played already with UI a little bit and using separate classes is pretty painful. Also I know I want to add new class to model in near future – my camera is able to make some simpler movie clips and why not to store clips in same system. Clips class will be almost like Photo but there are some more attributes. Adding another class to model in the way Photo is there makes coding more complex. So we need generalization.
GalleryItem class
I created class called GalleryItem as generalization of Album and Photo. GalleryIitem generates ID-s when new gallery item is added. As you may notice the associations on the model are same as before. I don’t want to change them now because currently I have no reason to play them around. My new model is shown on the following image.
Photo Gallery. Album and Photo are now subclasses of GalleryItem. Associations between
Album and Photo are same as before.
Refactoring existing model may be pretty hard headache on Entity Framework designer. It is still same raw and unstable as it has always been. No matter if you refactor existing model or create a new one, here are some guiding resources for you:
Database
To get better idea what is going on take a look at my database diagram. It looks almost the same as my class diagram. Database diagram below shows how to relate tables for table-per-type inheritance mapping.
Code
Due to these changes we have to modify also the source code of gallery. We have new class called GalleryItem and we have to change our custom context class MyGalleryEntities. Also Album and Photo have some changes. Let’s look at business classes first.
public abstract class GalleryItem
{
public virtual int Id { get; set; }
public virtual string Description { get; set; }
public virtual string Title { get; set; }
public virtual bool Visible { get; set; }
}
public class Album : GalleryItem
{
public virtual ICollection<Album> ChildAlbums { get; set; }
public virtual Album ParentAlbum { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
public virtual int ParentId { get; set; }
}
public class Photo : GalleryItem
{
public virtual Album Album { get; set; }
public virtual string FileName { get; set; }
public virtual bool IsGalleryThumb { get; set; }
}
Changes shoul be pretty straightforward. Only thing that model before doesn’t reflect visually is that GalleryItem is abstract class. We cannot create instances of it but we can extend it.
MyGalleryEntities class has no more separate properties for albums and photos. There is one property that returns ObjectSet of GalleryItems. We have to base all our queries on GalleryItems collection. Now let’s see new version of MyGalleryEntities class. NB! Don’t forget these two mandatory lines in constructor. Without them your collection and object references are always null.
public class MyGalleryEntities : ObjectContext
{
private ObjectSet<GalleryItem> _galleryItems;
public MyGalleryEntities() : base("Name=MyGalleryEntities")
{
DefaultContainerName = "MyGalleryEntities";
// MANDATORY LINES!!!
ContextOptions.DeferredLoadingEnabled = true;
ContextOptions.ProxyCreationEnabled = true;
_galleryItems = CreateObjectSet<GalleryItem>();
}
public ObjectSet<GalleryItem> GalleryItems
{
get { return _galleryItems; }
}
}
Here are some examples of queries against new MyGalleryEntities.
public void Examples()
{
var context = new MyGalleryEntities();
var all = from g in context.GalleryItems
select g;
var albums = from a in context.GalleryItems.OfType<Album>()
select a;
var photos = from p in context.GalleryItems.OfType<Photo>()
select p;
}
Now my gallery made through the first refactoring that touched database, model and source code. Everything works as expected and I can go on with other tasks on my gallery! :)
More Posts
« Previous page -
Next page »