Mindscape Mindblog

Archive for January, 2010

Screencast: LightSpeed + Dynamic Data = Win

I have just published a new screencast showing how to quick and easily create a dynamic data website that sits over a LightSpeed domain model. LightSpeed has been able to work with Dynamic Data for some time now but hopefully this screencast will help those who have not been aware that this could be done.

Topics covered:

  • LightSpeed enabling a Dynamic Data website
  • Improving the display of associated entities in display lists
  • Passing LightSpeed entity validation to Dynamic Data’s validation capabilities to improve the editing & creation process in Dynamic Data (This is a new feature a

What is dynamic data?

The official Microsoft description is “ASP.NET Dynamic Data provides a framework that enables you to quickly build a functional data-driven application, based on a LINQ to SQL or Entity Framework data model. It also adds great flexibility and functionality to the DetailsView, FormView, GridView, and ListView controls in the form of smart validation and the ability to easily change the display of these controls using templates.”

Of course now you don’t need to shackle yourself to L2S or L2E just to use Dynamic Data – you can work with your existing LightSpeed models :-) Watch the dynamic data screencast here (a direct download is also available if you do not like to watch flash videos in your browser)

I hope that helps!

WPF Diagrams: Custom Diagram Node Data

tag icon Tagged as WPF, WPF Diagramming

You may know that in WPF Flow Diagrams you can create your own custom node types to hold any additional data that they need. These nodes can be styled however you want, and also can be integrated into the serialization and undo features. This is useful when you want to create your own kind of node to represent a specific process that has its own attributes.

But what if you have various kinds of data objects that you want to be held by any type of diagram node? Or maybe you’re happy with the standard node types that we provide, but want them to hold more data without creating your own node types? Say for example you are creating a diagram where each node represents a task involved in completing a project. You may want each node including start and end nodes to contain text, as well as a list of people responsible for completing the task. Sure, you could create some custom node types that contain this additional data, but it would be nice if we could simply use the node’s Data property to hold any data we need

This has always been possible, but in the past it’s been slightly problematic due to the standard styles and serializer assuming that nodes only hold string content. However, if you download the latest update of WPF Flow Diagrams, you will find it is now easier to allow any kind of node to hold any kind of custom data that you need.

So you have some custom data objects that you want to be held by any node in a diagram. There are 2 main things you need to do: tell the diagram surface how to display the data content of a node, and tell the serializer how to serialize and deserialize your data objects.

Custom node content templates

The IDiagramFormatter interface now contains a property called NodeContentTemplateSelector. This can be set up to select a DataTemplate based on both the type of a diagram node, and the type of data that it holds. So you can have all nodes displaying each type of custom data the same way, or start nodes could display data differently to end nodes. So for each of the different types of node content that you want to display, you need to create a DataTemplate. These data templates will be templating your custom data, so you can have bindings to properties in your data objects to make them look however you want. Set these data templates into whatever data template selector you need, and set the selector into the NodeContentTemplateSelector of the IDiagramFormatter your using.

Here is an example of the effects you can achieve with templating custom node content.
(You can download this sample here to see how it works. Make sure you’ve also downloaded the latest update of WPF Flow Diagrams)

The start node simply contains a string. It gets a default template containing a TextBox where the text is a binding to the Data property of the node.

The next node contains custom data that has a string and an arbitrary object. The template selected for this type of node content displays the string but nothing else. This is useful when you want nodes to store custom data, but don’t want to change the appearance of the node.

The next node contains custom data that has a string and some data that represents a square. The template selected for this type of data displays the string, and also a coloured square. The template could also use attributes from the data to change the apperance of the square. For example its size and colour.

The last 2 nodes are different, but contain the same type of data. I have set up the template selector to use a different DataTemplate depending on the type of node ignoring the fact that the type of data is the same.

Custom node content serialization

Serializing your own custom data objects is fairly straight forward. IFlowDiagramSerializer now has a NodeContentSerializer property. All you need to do is make your own implementation of the new INodeContentSerializer interface. In the serialize method, you are given the data object that needs to be serialized. If you are serializing to XML, you just need to use the given XmlWriter to write any attributes your data objects have. If you have more than one type of custom data object, then you should also write some kind of attribute to the XmlWriter that indicates what type of data you are writing.

Now in the deserialize method, you get an XmlReader, and need to return an object. If you have multiple types of data objects, then you will first want to find out what type of object you are deserializing. This can be done by checking the value of the previously mentioned attribute. When you know what you are deserializing, you can read the values of the attributes that you wrote to XML, and create an instance of your data object based on these values.

If you haven’t tried the WPF Flow Diagrams yet and want to create some very slick looking diagrams then download the trial version now and let us know what you think!

Associations and composite keys

tag icon Tagged as LightSpeed

In previous articles, we’ve seen how to create and query for entities with composite keys in LightSpeed 3. But entities rarely exist in isolation: they have associations to other entities. In this article, we’ll see what how to set up associations to entities when composite keys are involved.

Refresher – association patterns in LightSpeed

As a reminder, a one-to-many LightSpeed association has two ends. At the parent end, there’ll be an EntityCollection of children. At the child end there’ll be an EntityHolder for its parent, and a scalar property for the foreign key to its parent (the parent Id). (In the designer, we hide the foreign key property, but it’s there all the same.)

One-to-one associations are similar, except they have an EntityHolder at both ends. Again, there’s a foreign key only at one end.

The association pattern and composite keys

The EntityCollection and EntityHolder classes are completely agnostic about the type of the foreign key. So the only thing we need to look at is the foreign key (parent ID). This has the be the same type as the Id of the entity it’s associating to. Well, in the case of a composite key, there’s a value type defined for that. So we just use that type for the foreign key field. But because this one field is going to be mapped to multiple columns in the database, we have to remember to specify ValueObjectAttribute on it. This tells LightSpeed to store each member of the structure in a separate column.

Here’s an example, where Product has a one-to-many association to Advert (omitting wrapper properties):

public class Product : Entity<ProductId>
{
  private readonly EntityCollection<Advert> _adverts = new EntityCollection<Advert>();
}
 
public class Advert : Entity<int>
{
  [ValueObject]
  private ProductId _productId;  // foreign key - note type and ValueObject attribute
  private readonly EntityHolder<Product> _product = new EntityHolder<Product>();
}

So associations with composite foreign keys follow the normal association pattern exactly, using the composite key struct as the foreign key type.

Database column mapping and associations

However, there’s a wrinkle. LightSpeed has the convention that a field in a value object field maps to a column whose name is the value object name followed by the field name. So, in the above example, in the Advert table, LightSpeed would expect to see columns named ProductIdProductTypeId and ProductIdCultureId. That’s pretty bad, but given that the whole reason for composite keys is that you’ve got a legacy database you can’t change, the chances of that legacy database having luckily adopted this naming convention are slightly lower than those of being run over by a train in your bathroom while you’re pretending to be an artichoke.

To customise the field mappings, you’d normally use ColumnAttribute, but you can’t in this case because there are multiple columns that need mapping. (When you apply ColumnAttribute to a value object, it modifies the prefix, but the individual fields keep the same names.) Instead, in this case we use the new ValueObjectColumnAttribute. This is specific to value objects and allows you to override each column mapping individually.

Let’s suppose that in the Advert table the product type ID column is called PTID and the culture ID column is called LANG_ID. (Don’t complain to me. It’s a legacy database.) Then we’d map our foreign key field like this:

public class Advert : Entity<int>
{
  [ValueObject]
  [ValueObjectColumn("ProductTypeId", "PTID")]
  [ValueObjectColumn("CultureId", "LANG_ID")]
  private ProductId _productId;
}

We’re done

And that’s it for composite keys. In this series, you’ve seen how to define entities with composite keys, how to query on the key, and how to define associations where the foreign key is composite. If you’ve got any more questions, or any feature requests around this, please post in the forum and let us know!

Querying and composite keys

tag icon Tagged as LightSpeed

In a previous episode, we saw how to define and create entities with composite keys in LightSpeed 3. It’s just barely possible you’ll want to get these entities back from the database at some point. In most cases, you’ll just do a Find or a LINQ query on the attributes you want to query on, just as you would with any other entity. But what if you want to query on the composite key itself?

Selecting an entity by ID

If you know the ID — or the ID components — of the entity you want to query for, you can get that entity using the familiar FindById (formerly known as FindOne) API:

ProductId id = new ProductId(2, "fr-CA");
Product product = _unitOfWork.FindById<Product>(id);

Selecting by partial ID

If you know part of the ID, and want to get all the entities that match that partial ID, you can use dot notation to specify that sub-attribute of the Id property. For example, suppose we want to find all Products for the French Canadian market:

var frenchCanadianProducts = _unitOfWork.Find<Product>(
  Entity.Attribute("Id.CultureId") == "fr-CA");

And of course you can combine this with other attribute queries or with other parts of the composite key:

var nonFrenchCanadianWidgets = _unitOfWork.Find<Product>(
  Entity.Attribute("Id.ProductTypeId") == widgetTypeId
    && Entity.Attribute("Id.CultureId") != "fr-CA");

That’s about it for things you need to know about querying composite-keyed entities. Next we’ll look at how associations work in the presence of composite keys.