Home » Blog

rounded header

Archive for September, 2010

Silverlight charts beta is now available

As promised recently, we’re announcing that early versions of our Silverlight Charts are now available in the nightly builds of Silverlight Elements. We elected to keep the charts as part of our Silverlight suite rather than spin it out as a separate product so that existing customers got some cool new controls and to make the Silverlight Elements suite even more compelling!

So what’s in the box at the moment?

Bar charts:

Silverlight bar chart with labels

Line charts:

Line chart in Silverlight

Pie & doughnut charts:

Pie chart with data labels in Silverlight

Remember: You can alter and customise the look and feel of the charts to your hearts content. Axis labels, data labels, colours, background grids, absolutely everything is customisable. If you make a particularly sexy chart then let us know, we’d love to see what users are building! :-)

As we are rolling out the charting beta in the nightly builds, you can expect new features and chart types every day. In the current nightly we’re shipping a Charting QuickStart sample and XML documentation, but we’re working on more detailed samples and improved documentation, and plan to ship those over the next couple of weeks. It is however a great time to provide feedback on the charts by telling us if there’s features you’d like to see, particular chart types you’d like us to prioritise or if you find the samples are not providing enough guidance — that sort of thing.

If you’re working with Silverlight and are curious about not only charting, but what else you get with Silverlight Elements you can read more on the Silverlight Elements site.

You can grab the latest nightly build of Silverlight Elements trial edition from the nightly build page, or get the full version from your account page in the store if you’re an existing customer.

Free software for user groups

Mindscape has always been very community oriented – many of the team speak at local user groups, Code Camps, Tech Ed, Unplugged events and so on. We’ve also been active in sponsoring community events like the Super Happy Dev House, NH-Day, Girl Geek Dinners and more. It’s time to do more however and we’ve been really pleased with the joint success we have had in helping user groups. Part of doing more is helping spread the word that we do want to help :-)

Our primary sponsorship method is to provide free software as prizes for user groups. We typically target Microsoft related user groups as our products are all in that space. So if you run a .NET/Silverlight/WPF/SQL Server/Microsoft Bob/C# user group, get in touch!

In retrospect, perhaps the Microsoft Bob user group was not quite ready for Ivan’s ‘Whirlwind Tour of LINQ Expression Trees.’

How does the process work for user groups?

Step 1: Get in touch
Email usergroups@mindscape.co.nz to tell us about your user group. We’re always keen to actually know the user group leaders and help them out in any way we can, so ping us an email and we can discuss what works for you.

Step 2: Eh? What?
There is no step 2. These are not the droids you’re looking for. Once we’re talking, we’re pretty quick to nail down our sponsorship based on your user group’s needs and organise how to provide the software.

What software do you provide?
We typically provide one free license to one of our products (excluding the Mega Packs) for each meeting. This works well because the folks running the event can choose a product that suits the audience. For example, if the topic is Silverlight related then our Silverlight Elements suite would likely go down well.

We also provide free software for speakers. Speaking for the first time in particular is really hard, we understand that, and we know user groups need a continuing stream of speakers in order to thrive. So to encourage people to take the leap, we offer a Mindscape Mega Pack — that’s every single developer tool we produce — to the speaker at each event.

Can you do me a favour?
Have you been to a local user group or do you know somebody involved in one? Please forward them a link to this post as we’d love to be connected with more user groups around the world. We currently sponsor about 15 user groups globally — and we want more right away :-)

Happy coding!

Nightly news, 17 September 2010

Another week draws to an end and we have a bumper crop of features and fixes in the latest nightly builds. Get ‘em while they’re hot!

LightSpeed

  • Added support for using the “is” operator on associated entities in LINQ queries
  • Added support for using non-database-backed properties in LINQ expressions
  • Added support for string concatenation in LINQ expressions on non-SQL Server databases
  • Added wildcard column exclusion to lsgen command-line tool
  • Provided a more meaningful error if the LockVersion field was declared incorrectly
  • Added an option to have sequence allocation run up to the returned sequence value instead of behind it
  • Fixed a bug with function arguments which themselves had functions applied to them
  • Fix for nested Any calls in a Where clause where the nested Any doesn’t have a predicate
  • Fixes for designer NoReverseAssociationAttribute support
  • Added fixes for hyphenated domain names in SimpleDB
  • Provided a workaround for Visual Studio 2010 Server Explorer not allowing connections to SQL Server 2000 except through OLE DB

WPF Elements

  • Fix for drop-down not appearing for enum values in the property grid when displaying a weak-typed ObservableDictionary
  • Added RichTextBox support to the PromptDecorator

WPF Diagramming

  • Tweak to make it easier for applications to detect when diagram elements have moved

Free editions from the downloads page, retail editions from the store.

Ninja domain properties in LightSpeed

tag icon Tagged as LightSpeed

When you’re modelling a domain, it makes sense to provide attributes and methods on your domain objects to encapsulate domain logic. The alternative is the anaemic domain model anti-pattern, where the domain classes are dumb record types and domain logic is exiled to separate service classes. Most modern object relational mappers, including LightSpeed, support rich domain models: for example, in the LightSpeed designer you can create partial classes where you can add your own properties and methods that contain this domain logic.

The trouble with this simple approach is that it doesn’t play nicely with querying. Users of the domain model need to know which properties and methods are part of the persistence model and which are not. For example, suppose we have a Person class in our domain model, with FirstName, LastName and FullName properties, where FullName is computed from FirstName and LastName. Let’s write some queries:

unitOfWork.People.Where(p => p.FirstName == "Enguerrand");  // works
unitOfWork.People.Where(p => p.LastName == "de Coucy");  // works
unitOfWork.People.Where(p => p.FullName == "Enguerrand de Coucy");  // oh noes!

The problem of course is that in the third case the ORM needs to generate SQL along the lines of WHERE FullName = ..., which fails because there’s no FullName column — the FullName property exists only in the object realm. A similar issue applies to using FullName in ordering clauses, or to selecting FullName as part of a LINQ projection.

So the FullName property is a bit of a second-class citizen. And users of the Person class are forced to know about the database model, not just the domain model. The domain abstraction leaks like Scott Barnes after a crate of Fosters.

What we’d like is to express the FullName logic in such a way that it can be translated into SQL, and to have the ORM perform that translation for us.

The LightSpeed translation convention

The latest LightSpeed nightly builds adopt a convention by which you can specify a translation for computed properties such as FullName. The convention is that LightSpeed will look for a static field with the same name as the property with the suffix “Expression”, and of lambda expression type. Here’s an example:

// Property in Person class
public string FullName {
  get { return FirstName + " " + LastName; }
}
 
// Query expression in Person class corresponding to FullName property
// Note field type must be Expression<Func<entity_type, domain_property_type>>
private static readonly Expression<Func<Person, string>> FullNameExpression = 
  p => p.FirstName + " " + p.LastName;

As you can see, the logic of FullNameExpression is exactly the same as the way you’d normally implement the FullName getter — you just need to put it into lambda notation.

With this expression in place, when LightSpeed encounters FullName in a Where, OrderBy or Select clause, it will quietly translate it into FirstName + " " + LastName, and go on and translate that to SQL:

// C# query
UnitOfWork.People.Where(p => p.FullName == "Enguerrand de Coucy");
 
// Generated SQL (SQL Server dialect; will vary on other platforms)
SELECT
  -- details omitted
FROM
  Person
WHERE
  ((Person.FirstName + ' ') + Person.LastName) = 'Enguerrand de Coucy'

So now the FullName property works just like the FirstName and LastName properties as far as querying, sorting and projection are concerned. Users of your domain model don’t need to know that FullName isn’t a database column.

The convention also applies to domain methods, which can be useful if you have domain logic which requires additional data to evaluate a value. Again, you need a field with the “Expression” suffix and of lambda type. The first parameter of the expression is the domain object, and each method argument maps to another expression parameter. Again, this is probably clearer with an example:

// Method in Person class
public int AgeInYear(int year)
{
  return year - BirthDate.Year;
}
 
// Query expression in Person class corresponding to AgeInYear method
// Notice second parameter of type int corresponding to "year" method argument
private static readonly Expression<Func<Person, int, int>> AgeInYearExpression =
  (p, year) => year - p.BirthDate.Year;
 
// C# query
var query = unitOfWork.People.Where(p => p.AgeInYear(2020) >= 18);
 
// Generated SQL (SQL Server dialect; will vary on other platforms)
SELECT
  -- details omitted
FROM
  Person
WHERE
  (2020 - DATEPART(YEAR, Person.BirthDate)) >= 18

Of course, the expression still has to be translatable to SQL on your particular database platform. So the abstraction is far from perfect, especially when you start dealing with complex data types or complicated logic. (And some database platforms have restrictions on the kind of expressions that can be used in SELECT or ORDER BY clauses which can prevent even relatively simple logic from running server-side.) But for many simple computed domain values this technique means that your users can use arbitrary properties and methods in their LINQ queries without needing to worry about which ones are mapped directly to the database and which ones aren’t.

I see dead code

One thing you may find offensive is that we are duplicating logic across the CLR property or method and its translation expression. Code duplication is bad, right? What if we had to change the FullName or AgeInYear logic? We’d need to remember to update it in both the property getter and the expression field. Can’t we write the domain logic once and have it magically appear in both places?

Well, until the C# language team give us macro support, which we are promised will be shortly after hell freezes over, there’s no ideal solution to this. However, there is a non-ideal solution which may suffice for some scenarios. Lambda expressions support a Compile() method which compiles the expression into a CLR delegate. So if you compile, say, the FullNameExpression and call it on the this reference, you can avoid the code duplication:

public string FullName {
  get { return FullNameExpression.Compile()(this); }  // careful now!
}

As written, though, you pay a terrible price for this: the expression is recompiled every time you call the property getter. This is far, far slower than if you’d just written the duplicate code in the property getter — though still only a few microseconds for a simple expression. By caching the compilation result you can bring this down to a manageable amount, but it will still be slower than plain code. So you can improve maintainability but at the cost of performance; and as always with performance tradeoffs, you can only make the right decision by measuring the actual performance impact in your target scenarios. (As an indicator, the overhead we’re talking about might be between 10 and 100 nanoseconds depending on your caching mechanism. But don’t use my figures. Measure it!)

Yeah! I’ve had it with anaemic domain models! I want to start enriching my domain model right now!

Magic expressions are in the current LightSpeed nightly build. If you want to take them for a spin, grab the free edition from the downloads page, or the retail edition from the store. This feature is currently experimental so be sure to let us know how it works for you or if you run into any bugs! Enjoy!

Mindscape @ TechEd NZ 2010 Videos

tag icon Tagged as Events, General

Can’t get enough Mindscape action? Want hours and hours of footage to watch alone at home in the dark?

Microsoft have hosted the sessions that Jeremy, Ivan and I delivered at Tech Ed New Zealand this year so grab a family sized bucket of chicken, kick back and enjoy:

Happy coding!

Data Products Visual Controls Community Store
LightSpeed ORM
NHibernate Designer
SimpleDB Tools
SharePoint Tools
WPF Elements
WPF Diagrams
Silverlight Elements
Forums
Blog
Register
Login
Subscribe to newsletter
Buy Now
My Account
Volume Discounts
Purchase Orders
Contact Us