Archive for June, 2008
Applying validations to LightSpeed models
Tagged as LightSpeedLightSpeed allows you to specify constraints on entity attribute values. For example, on a Person entity, you might specify that Name must be present, that Email must be in email address format and HomePage in URL format, and that Age must be in the range 0 to 150. You specify these constraints in your entity code by placing attributes on the entity fields.
If you’re using the LightSpeed designer, it generates the field declarations for you, so you need to specify the validations in your model. There are two ways to do this: the “real” way which gives you access to the full validation capabilities of LightSpeed, and a shortcut way which you may find quicker and more convenient once you know how to use it.
The “real” way uses the LightSpeed Model Explorer, the Solution Explorer-like tree that shows you the entire contents of your model. If you can’t see this window, open a LightSpeed model, and go to View > Other Windows > LightSpeed Model. Expand the tree until you find the property you want to validate. Now right-click it and add the validation or validations you want.

The validations for a property are listed under its Validations folder in the LightSpeed Model Explorer. Click on a validation in the Explorer to edit its details in the Properties window.

A lot of the time you don’t need this level of fine control over validations. So the designer also offers shortcuts: if you select a property, the Properties window displays a number of validation options. Most of these are self-explanatory — for example you can use the Validate Presence property to toggle presence validation on or off. Validate Length and Validate Value are a little more complex: they use a C#-like syntax, which is described in the User Guide under Help Topics > Generating LightSpeed Models. Here are our Message validations being edited via their shortcuts:

The main limitation of the shortcuts is that you can’t specify a custom error message. However, all the shortcuts actually do is display, create and edit validations in the tree: for example if you toggle Validate Email to True in the Properties window, behind the scenes this just adds an Email Validation in the tree. So if you create a validation using a shortcut, you can always use the Model Explorer to edit it later and add a custom error message. Also, there’s no shortcut for custom validations; you have to create those via the Model Explorer. (There are also some edge cases that you might be able to represent with a combination of Range and Value validations in the tree, but can’t express using the Validate Value shortcut. For example, value must be between -10 and +10, but must not equal 0. We think these are more theoretical than actual, though.)
Whichever way you edit the validations, the result is the same: the appropriate attributes are placed against the generated field in the entity code, and the LightSpeed validation infrastructure does the rest.
Want to try it out? LightSpeed Express is free, even for commercial use — download it and have a go.
Designing LightSpeed models
Tagged as LightSpeedLightSpeed is a domain modelling tool. It prescribes some simple, predictable rules for expressing your domain model in object-oriented code and in relational database tables; if you follow these rules then LightSpeed takes care of the work of translating between the object and relational worlds, allowing you to focus on doing whatever it is you want to do at the domain level, rather than thinking about data plumbing.
And the great thing about simple, predictable rules is that you can make computers do the grunt work for you.
Imagine being able to design your domain model in the abstract: that is, instead of having to create separate representations of your model in the code notation and the relational notation, imagine being able to design the model using a model notation, and get the computer to translate that into the corresponding object and relational implementations using the LightSpeed rules.
Well, unfortunately, you’re going to have to keep imagining a little longer. But LightSpeed 2 is a small step in that direction. It gives you a way to design your models visually, using a simple graphical notation. As you do so, your models are automatically translated into C# or Visual Basic. Models aren’t currently translated into relational database schemas, because this introduces some additional complexities around versioning and migration, though there is a basic facility for updating your development database, intended to support rapid prototyping. (I’ll say more about this in a later post.)
In order to use the designer, you’ll need to have Visual Studio 2008, Standard Edition or higher, installed. (Sorry, the designer doesn’t currently support VS2005, and Microsoft don’t allow add-ins in the Express editions.) If you’ve got that, install LightSpeed — you can use the free Express edition — making sure that the “LightSpeed Model Designer” option is selected and you’re ready to go.
Start by creating a new C# or Visual Basic project.
Now right-click the project and choose Add New Item. Look under Data, and you’ll see that you now have the option to create a LightSpeed model:
This brings up an empty designer surface and a toolbox of things you can put on there. For most models, the interesting toolbox items are Entity and OneToManyAssociation, though the designer also supports value objects, one-to-one associations and inheritance.
Drag the Entity icon from the toolbox to the designer. Once you’ve created an entity, you can rename it through the Properties window or by double-clicking its title. (You can also use the Properties window to customise the behaviour of the entity, but we won’t discuss that right now.)
To add properties to your entity, right-click it and choose Add New Entity Property. You can edit the name of the property in place. To specify the data type, use the Properties window. You can also edit the name here, and as with entities you can customise the behaviour (again, we won’t go into that now).
Saving the model causes Visual Studio to generate appropriate C# or Visual Basic code:
If your project targets .NET 3.5 or above, the generated code includes a strong-typed unit of work class so that you can use LINQ. The designer also adds references to the LightSpeed (and, if appropriate, LINQ to LightSpeed) assemblies if the project doesn’t already have them.
To create associations between entities, select the OneToManyAssociation tool from the toolbox, and drag it from one entity to another. (Start at the “one” end and drag to the “many” end. For example, if a Contribution has many Comments, but each Comment applies to only one Contribution, you’d drag from Contribution to Comment.) The designer infers appropriate property names for each end of the association, though you can edit these if you want to (and you will need to if you have more than one association between the same two entities).
Notice that you don’t need to create a property to contain the ID of the referenced entity. For example, in the Comment entity above, you don’t have to create a ContributionId property. When the designer generates code for the association, it generates a ContributionId property as well as the Contribution EntityHolder. Notice also that you don’t need to define both the one-to-many association and the reverse many-to-one association. Again, the designer generates code into both the Contribution and Comment classes, handling both ends of the association.
This gives you some idea of how LightSpeed 2 enables you to perform domain modelling in the abstract, with automatic generation of the code.
Q. You and your fancypants domain modelling. Here in the real world, I have a database, and I need to get stuff into and out of it. Can your designer help me with that?
A. Yes. You can drag tables from Server Explorer onto the design surface, and LightSpeed will create appropriate model entities and relationships. And if you subsequently edit the table design in your database tool, LightSpeed can update the model to reflect your changes. (We might venture to suggest that, in this scenario, you’re almost using your database tool as your domain modeller, and using the designer to translate that into the code representation. But that’s just us and our fancypants domain modelling.) Here’s an example:
LightSpeed not only creates entities for the database tables, and properties for the columns, it also infers associations between them based on foreign key relationships. You can now save the model to generate the LightSpeed code. Of course, you can also edit the model further, for example to customise caching or eager loading. Additionally, LightSpeed remembers which database the entities were created from, so that it can keep the abstract model in sync with the database representation. I’ll talk more about this in a future post.
The designer is included with all editions of LightSpeed. If you want to take it for a test drive, download the free LightSpeed Express edition and give it a go!
Using LightSpeed-specific features from LINQ
Tagged as LightSpeedLightSpeed 2 includes a LINQ provider that allows you to write queries against LightSpeed using the standard LINQ syntax, such as the following:
var query = from m in UnitOfWork.Members where m.UserName == "jb" select m;
However LightSpeed offers some features that the standard LINQ syntax doesn’t support. Specifically LightSpeed allows you to control, using named aggregates, when associations or large data objects are loaded, and it supports “soft deletion” including the retrieval of soft-deleted data.
The LightSpeed LINQ provider supports named aggregates via a special WithAggregate query operator. Here’s an example of how you would force a set of Contributions (from the LightSpeed samples) to load with the ContributionDetail named aggregate:
var query = from c in UnitOfWork.Contributions where c.Title.StartsWith("A") select c; var contributions = query.WithAggregate("ContributionDetail").ToList();
This is equivalent to setting the AggregateName property on a LightSpeed Query object.
As for soft deletion, the soft delete functionality itself happens automatically at the LightSpeed engine level. The only extension is a way to include soft-deleted items in the LINQ query. This is done using the IncludeDeleted query operator:
var query = from a in UnitOfWork.Accounts select a; var accounts = query.IncludeDeleted().ToList();
This is equivalent to setting the IncludeDeleted property on a LightSpeed Query object.
By using these two custom operators you can continue to access these LightSpeed features from within LINQ.
When should I use LINQ in LightSpeed 2?
Tagged as LightSpeedOne of our LightSpeed 2 Early Adopter customers posted a query in the forums about the tradeoffs between using LINQ compared to the traditional LightSpeed Find method to implement the Repository pattern. We provide a sample of this pattern that looks something like this:
public interface ICatalogRepository : IRepository { IEnumerable<Category> Categories { get; } IEnumerable<Supplier> Suppliers { get; } // other members elided for clarity } public class CatalogRepository : RepositoryBase<NorthwindUnitOfWork>, ICatalogRepository { public IEnumerable<Category> Categories { get { return UnitOfWorkScope.Current.Find<Category>(); } } // other members elided for clarity }
The customer had changed the implementation as follows:
public IEnumerable<Category> Categories { get { from c in UnitOfWorkScope.Current.Categories select c; } }
and was interested to know the benefits of one approach over the other.
Well, to an extent, this is a matter of taste. As the customer had already discovered, LightSpeed generates the same SQL for the LINQ and “native” queries. The reason for this is simple: the LINQ query eventually resolves into a Find call anyway!
In fact, in general, there’s no difference in efficiency between LINQ and “native” queries. Any LINQ query eventually gets translated into a Query object and an IUnitOfWork method call, and executes with the same efficiency as if you had constructed the Query object and called the method “manually”. Consequently, not only do LINQ queries inherit the optimisation provided by the core LightSpeed engine, but they also respect tuning and behavioural settings such as caching, eager/lazy loading, soft delete, and so on.
So at the simple end of the scale it’s largely down to which syntax you prefer:
var allProducts1 = unitOfWork.Find<Product>(); var allProducts2 = from p in unitOfWork.Products select p; var allProducts3 = unitOfWork.Products; // equivalent to allProducts2 var cheapProducts1 = unitOfWork.Find<Product>(Entity.Attribute("Price") < 100); var cheapProducts2 = from p in unitOfWork.Products where p.Price < 100 select p; var cheapProducts3 = unitOfWork.Products.Where(p.Price < 100); // equivalent to cheapProducts2
There are two cases where the two syntaxes are functionally different. The first is if you need to perform a query on an attribute which is only known at runtime. Perhaps your application allows the user to select which field to sort on:
string sortField = GetSortFieldFromUI(); Query query = new Query { Order = Order.By(sortField) }; var topItems = unitOfWork.Find<Widget>(query);
You can’t do this in LINQ because LINQ needs to resolve the orderby expression at compile time:
var topItems = from w in unitOfWork.Widgets orderby w.??? select w;
The second is that LINQ queries are not executed until you actually use them, for example in a foreach. For example, suppose you are writing a desktop application and you are concerned that your UI might become unresponsive during a database query. You might therefore want to control when the database access occurs, for example at startup or in a background thread. In this case, you should use the Find syntax, or call ToList() or ToArray() on the LINQ query to force it to execute then and there.
Complex Expressions in Queries
When you start dealing with more complex expressions in queries, we recommend using LINQ because it enables you to use your familiar C# or Visual Basic syntax and keep the query expressions concise. For example, consider the following LINQ query:
from sl in unitOfWork.SalesLines where sl.UnitPrice * sl.Quantity > 1000 select sl;
It’s perfectly possible to express this in LightSpeed 2 — otherwise LINQ couldn’t do it — but because we expect a lot of users to adopt LINQ for these purposes, we haven’t tried to optimise the syntax at the QueryExpression level:
unitOfWork.Find<SalesLine>( Entity.Attribute("UnitPrice").Function( "*", Entity.Attribute("Quantity")) > 1000);
LINQ’s use of CLR expressions comes in doubly handy when you’re dealing with a function that is implemented differently in different SQL dialects. We wouldn’t recommend using the Find syntax for, for example, these:
// Might call LEN or LENGTH from ct in unitOfWork.Comments where ct.Message.Length > 100; // Might call YEAR, DATEPART, DATE_PART, TO_CHAR('YYYY')... from m in unitOfWork.Members where m.JoinedOn.Year <= 2007;
Of course, this cuts both ways. If the SQL function you want to use in your query expression doesn’t have a CLR equivalent, or the CLR equivalent isn’t supported in LINQ to LightSpeed, then you must use QueryExpressions and Find instead of LINQ.
Projections
If you’re using projections, you should definitely consider using LINQ. Again, a projection query resolves down to a call to IUnitOfWork.Project(), so there’s no difference in efficiency or in the generated SQL, but in many cases LINQ makes it easier to work with the results of the projection. For example:
from p in unitOfWork.Products select new { p.Name, p.Price }; // anonymous type from p in unitOfWork.Products select new ProductSummary { Name = p.Name, Cost = p.Price }; // named type
When you know at design time which fields you’re working with, this is more convenient than getting the results out of an IDataReader. On the other hand, if you have a more dynamic system in which the fields you’re querying on may vary depending on user input, you won’t be able to use LINQ and should instead use IUnitOfWork.Project().
API Design Considerations
Look again at the ICategoryRepository API and the CategoryRepository implementation above. These work well if all the application code wants to do is enumerate the categories. But what if application code wants to filter the result set, or perform ordering? The repository author is faced with a decision: does he try to anticipate application requirements by creating a flexible query API, or does he try to anticipate likely queries and encapsulate them within his API? And how can he possibly anticipate the application’s future requirements — what if the application later needs to do paging as well as ordering?
Of course, the application can write LINQ queries against the Categories property:
from c in repository.Categories where c.Name == "Rayguns" orderby c.Popularity select c.Code
But, because Categories is IEnumerable
One possible way out of this is to reformulate the API and implementation as follows:
public interface ICatalogRepository : IRepository { IQueryable<Category> Categories { get; } } public class CatalogRepository : RepositoryBase<NorthwindUnitOfWork>, ICatalogRepository { public IQueryable<Category> Categories { get { from c in UnitOfWorkScope.Current.Categories select c; } // Equivalently: get { return UnitOfWorkScope.Current.Query<Category>(); } // Equivalently: get { return UnitOfWorkScope.Current.Categories; } } }
Now, when the application performs a query against repository.Categories, LINQ notices that Categories is IQueryable rather than merely IEnumerable, and hands the query to LightSpeed to perform on the server. We have given application code the power to query the repository flexibly without having to anticipate its requirements in our repository API.
Another interesting side of this is when you consider other LINQ operators that can’t be efficiently implemented in terms of Find. Suppose the application needs to know how many categories there are. Again, getting the result of Find and calling Count against it would be woefully inefficient. Instead we want to call the LightSpeed IUnitOfWork.Count method. But the unit of work is encapsulated in the repository and the application code can’t get at it. So again the repository designer has to anticipate the application requirement and add a CategoryCount property to the repository API. Then next day someone needs a method to get the total number (IUnitOfWork.Calculate(“SUM”)) of sales across a certain line of products… But if the repository returns IQueryable objects, then LINQ allows application code to perform these queries against it and have them translated into IUnitOfWork.Count() and IUnitOfWork.Calculate() methods and hence into efficient SQL, with no need for additional complexity in the repository API:
int count = repository.Categories.Count(); // generated SQL: SELECT COUNT(*) FROM Categories int totalSales = repository.Products.Sum(p => p.NumberSold); // generated SQL: SELECT SUM(NumberSold) FROM Products int raygunSales = (from p in repository.Products where p.ProductType == "Raygun" select p.NumberSold).Sum();
So you should consider using LINQ rather than Find for repository APIs where it is desirable for applications to be able to compose their own queries.
Conclusion
There are a few scenarios in which you will not be able to use LINQ: notably, if you want to use a SQL function that has no CLR equivalent, or if you need to be able to choose the fields involved in a projection, predicate or order at run time instead of design time. And you may not be able to use LINQ at all because you don’t want to migrate your project to .NET 3.5 for stability or deployment reasons. In these cases, you can of course still use the “native” IUnitOfWork interface and its Find, Project and Count methods. (And you can mix and match the LINQ syntax and native API within the same unit of work.)
In general, however, we recommend using the LINQ syntax for new LightSpeed query code if you are targeting .NET 3.5 or above. You will benefit from easier access to complex expressions and projections, and it will make it easier for developers from non-LightSpeed environments to get up to speed on your project. You can still tune your loading and caching strategies at the entity level, and because LINQ uses the LightSpeed engine, these strategies will still be respected. And because LINQ queries are translated into the equivalent calls to the LightSpeed engine, you are losing nothing in the way of efficiency or quality of generated SQL.
Introducing LINQ to LightSpeed
Tagged as LightSpeedAs Andrew mentions in his overview, LightSpeed 2 incorporates LINQ (Language Integrated Query) support. If you’re using C# 3.0 or Visual Basic 9, and targeting .NET 3.5 or above, LINQ brings the concept of querying directly into the language core, so instead of writing a SQL statement and embedding it as quoted string, you can write the query using C# or Visual Basic syntax. Among the benefits of LINQ are compile-time type checking, saving you learning (and writing) the details of the SQL syntax and the fact that the LINQ implementation can optimise the way it handles your query, for example optimising the SQL or parallelising an in-memory query.
Of course, LightSpeed 1 already provided these benefits to a great extent. The LightSpeed query API saved you from having to put together SQL strings, set up SQL parameters, and so on. LightSpeed queries returned entity objects instead of data readers, so you had typed objects from the start. And the LightSpeed engine created optimised, database-specific SQL from your abstract query description.
LINQ to LightSpeed means that if you know LINQ, you can get these benefits without having to learn a new API. You can continue to write LINQ queries as if against LINQ to SQL or another LINQ provider, but you’ll get database independence (effectively LightSpeed gives you LINQ to Oracle, LINQ to MySQL, LINQ to PostgreSQL and LINQ to SQLite as well as LINQ to SQL Server, all in the one box), advanced eager loading functionality (avoiding the so-called “n+1″ problem which affects some LINQ implementations) and of course the blazingly fast LightSpeed query engine.
In order to use LINQ to LightSpeed, you’ll need to add a reference to Mindscape.LightSpeed.Linq.dll to your project. This defines the extension method Query on IUnitOfWork. So now (with the appropriate using statement), you can write:
var query = unitOfWork.Query<Member>(); var everyoneExceptJB = from m in query where m.UserName != "jb" select m;
We don’t really want to be writing unitOfWork.Query
using Mindscape.LightSpeed.Linq; // to bring extension method into scope public class VideoSharingUnitOfWork : UnitOfWork { public IQueryable<Member> Members { get { return this.Query<Member>(); } } }
A bonus of this is that we no longer need to have a using clause for the extension method in our querying code — only the convenience class needs to see the extension method. By the way, if you use the Visual Studio LightSpeed designer to create your models, it automatically creates this class for you. (The designer will also add the LINQ DLL reference if required.)
Also, because VideoSharingUnitOfWork is an IUnitOfWork, we can still call the usual methods on it for updates: e.g. Add(entity), Remove(entity), SaveChanges, etc. These don’t change just because we’re using LINQ to write queries.
If we create this convenience unit of work class, we need a way get an instance of it. LightSpeedContext.CreateUnitOfWork() returns a “normal” IUnitOfWork, not our convenience class. What we need to do instead is call ==LightSpeedContext<VideoSharingUnitOfWork>.CreateUnitOfWork()==. ==LightSpeedContext<TUnitOfWork>== is exactly like LightSpeedContext except that CreateUnitOfWork() returns the convenience class rather than the base IUnitOfWork interface. (The scope helper classes in LightSpeed 2 also support convenience unit of work classes.)
So with the plumbing out of the way, we can write our LINQ query as follows:
var everyoneExceptJB = from m in unitOfWork.Members where m.UserName != "jb" select m;
And of course now we have a queryable Members object we can go on to write more complex queries:
var matureAdults = from m in unitOfWork.Members where m.Age > 21 && m.UserName != "ludwigthemad" orderby m.FeedbackRating descending select m;
And projections:
var exMembers = from m in unitOfWork.Members where m.Expired select m.UserName; var memberSummary = from m in unitOfWork.Members orderby m.UserName select new { m.UserName, m.MemberSince, m.LastLogin };
Most of the time, you’ll be iterating over the results of a query:
foreach (var adult in matureAdults) { Console.WriteLine(adult.Name + " is no longer one of the cool kids"); }
In this case, the LINQ query behaves just like a traditional LightSpeed query. You get back some entities, and you work with those.
But iteration isn’t the only thing you can do with LINQ queries.
int adultCount = matureAdults.Count();
When you execute the line above, LightSpeed issues a Count query, not a Find query. As with a native LightSpeed Count query, this becomes a SQL COUNT and is executed on the database. Count isn’t the only operation for which this happens:
int oldest = unitOfWork.Members.Max(m => m.Age); int youngest = unitOfWork.Members.Min(m => m.Age); int ifYouLaidThemAllEndToEnd = unitOfWork.Members.Sum(m => m.Height); bool gotYoungsters = unitOfWork.Members.Any(m => m.Age < 16);
And if you haven’t used LINQ before you may be surprised to find that you can even use some .NET methods and operators, and LightSpeed will execute them on the database:
var allTheJs = from m in unitOfWork.Members where m.UserName.StartsWith("j") select m; var revenue = from o in unitOfWork.Orders where o.BookedDate >= periodStart && o.BookedDate <= periodEnd select o.UnitPrice * o.Quantity * (100.0 - o.Discount) / 100.0;
We won’t go into LINQ examples in any more detail, as there are plenty of resources out there for learning the LINQ syntax, and for the most part they apply without any changes to LINQ to LightSpeed. So all you need to remember that’s specific to LightSpeed is:
- Reference the LINQ DLL.
- Optionally, create a strong-typed unit of work (convenience class), or use the designer which will create one for you.
- If you’re using a strong-typed unit of work, use ==LightSpeedContext<TUnitOfWork>== instead of the base LightSpeedContext.
Want to give it a try? Get LightSpeedExpress (it’s free, even for commercial use) and give it a go!
Categories
BrainDump (1)
Community Code (4)
Events (16)
F# (14)
General (53)
Lab Samples (2)
LightSpeed (268)
MegaPack (8)
News (71)
NHibernate Designer (26)
Nightly news (52)
Phone Elements (24)
Products (87)
Projects (5)
Screencast (6)
SharePoint (3)
Silverlight (14)
Silverlight Elements (66)
SimpleDB Management Tools (20)
Visual Studio (9)
VS File Explorer (7)
Web Workbench (39)
WPF (44)
WPF Diagrams (57)
WPF Elements (110)
WPF Property Grid (32)



Posted by Ivan Towlson on 15 June 2008 








