Saturday, September 4, 2010

DevForce Meets Mvvm Light

Model-View-ViewModel (MVVM) is THE most successful UI development paradigm ever …  measured by the number and variety of people talking about it. I don’t recall anything like this level of interest with respect to MVP or MVC. For most of UI history the majority of developers couldn’t name the pattern they were using … if they even thought they had a pattern. “MVC”, for most people, is a technology, not a design pattern.

Today, MVVM is the jargon-du-jour. And I think that’s a good thing.

We should retain some perspective. Not every view must be MVVM. And yet a healthy number of WPF/Silverlight screens should be done in MVVM style and I’d want to have a really good reason to depart from that standard.

How do you write a screen in MVVM style? Do you need a framework?

Some people think you do. There are plenty to choose from. And Laurent Bugnion’s “MVVM Light” has to be the most popular of the ulta-lightweight choices.

One of our customers asked for an example of DevForce and Mvvm Light working together. I put such an example together and made it available on the “DevForce Resource Center” (DRC); the Mvvm Light example page is here.

I provide code that shows three ways to start a DevForce + Mvvm Light application and one “Hello World” example.

Blend is a critical part of the story. “Blendability” is central to the Mvvm Light philosophy … and I agree. The working example view was written entirely in Blend.

Expect more from me soon on developing with Blend.

Meanwhile, here’s your launch point for Mvvm Light with DevForce.

Enjoy!

Friday, August 20, 2010

DevForce “Blends”

We are seeing an increasing interest among developers in using Blend to design application views. I think this is great. Silverlight and WPF are great technologies for building productive business applications. But you can’t be as productive and effective as you should be if you only work in XAML. You need the tools.

And Blend 4 is an incredibly great tool. I say this even though I’m only competent to use about $1.30 of it.

All of this is preface to a forum question we received:

I’m attempting to mock data at *design* time. … Has anyone ever managed to get this to work? …Using DF to avoid creating dozens of mock repositories on a large project? Now that would be a coup!

My answer follows:

We are well on our way to making DevForce play well with Blend. Actually, we probably are THERE. But we haven't documented it well and I don't feel that I'm particularly close to anything worthy of calling a "Best Practice." Let's say I have some "ok" practices :-/

Here's visual evidence of an existence proof: yes, you truly can use a DevForce EntityManager and entities at design time:

ComboBox Sample in Blend

This example comes from my slight re-design of the "Simple ComboBox in Silverlight" sample code.

[Aside: the existing sample is on our web site now. The revised one will be released with our forthcoming "DevForce Cookbook." Look for the Cookbook to arrive within a matter of weeks.]

The original point of the sample was to demonstrate how to wire up a ComboBox to DevForce entities AND bind that ComboBox to other DevForce entities.

The previous version looked bloody awful; this one just looks bad.

However, it's beautiful for the purpose of this forum post! You can plainly see employee, "Ima", in on the Blend art board. "Ima" does not exist in the Northwind tutorial database. She's a fake Employee, ginned up in a MainPageDesignViewModel that derives from the production MainPageViewModel. The view doesn't know; it's just binding to a ViewModel (VM).

All of the fakery happens in the design VM's constructor, shown here:

    public MainPageDesignViewModel() {

EntityManager = new NorthwindManager(false);
EntityManager.DefaultQueryStrategy = QueryStrategy.CacheOnly;

var designEmp = new Employee {
EmployeeID = 1, FirstName = "Ima", LastName = "Blast", ReportsToEmployeeID = 2,
};
var designManagerEmp = new Employee {
EmployeeID = 2, FirstName = "Slim", LastName = "Ornun", ReportsToEmployeeID = null,

EntityManager.AttachEntity(designEmp);
EntityManager.AttachEntity(designManagerEmp

PotentialManagers = new List<Employee> { designManagerEmp };
CurrentEmployee = designEmp;
Messages.Add("We're in DesignTime now !!!");
}

The design version of the VM (a) creates two fake employess (Ima and her boss, Slim), (b) creates a disconnected, cache-only EntityManager (EM) - to ensure there is no attempt to talk to the database, and (c) adds the two employees to that EM. Because both fakes are in cache, DevForce can implement the navigation between Ima and Slim via the "Manager" property. I neglected to show this in the ComboBox but you can see it in the message which reads "Ima Blase whose manager is Slim Ornun".

It is only a few short hops from here to doing the cache-to-file trick that you want. In fact, I've done what you want on a different project and we'll provide a similar, smaller example in one of the Cookbook recipes .... although perhaps not in the first Cookbook edition. Trust me, it works great.

To be precise, it worked great for test runs of your application that you wanted to be fast and free of the need to talk to a database. It didn't work in Blend (although for different reasons than Jason cites).

Until DF 2010 v. 6.0.5, it simply wasn't viable to use DF entities in Cider (Visual Studio visual designer) or Blend because we required that the Desktop (aka Web aka "Full DotNet") model carry the same assembly name as the Silverlight model. No problem for the CLR but most tools, including design tools, just choked.

Using the same assembly name is no longer required. In fact, is heavily discouraged.

Now this ComboBox sample dates from 6.0.2 (I think) ... certainly before we got rid of the assembly name restriction. It did not Blend.

All I had to do was some assembly renaming plus clean and re-build. The view popped right up in Cider and Blend.

There was no data visualization though. Just a bunch of weird boxes. The XAML looked ok ... obviously it ran ok ... but it made no sense rendered in Cider or Blend.

A little dragging around was helpful but I still wanted to see sample data.

So I refactored the ViewModel to facilitate a derived, design-time version of that ViewModel and, presto, that's how I was able to get the layout you see in the image above.

[While I was at it, I replaced the button click wiring with Blend Behaviors ... and deleted the entire custom code-behind]

You can do the same things to your application, or wait for the Cookbook if you want to see the details.

As I mentioned, the cache-to-file variation is not far off. That will take some explanation, however, as there are a few places you can stumble on the way ... as you discovered. Please hang in there.

Monday, August 9, 2010

DevForce in the Cloud: Prism Explorer

On our second flight to Azure, we deployed our “Prism Explorer” sample application. The address is the same as before: http://dftest003.cloudapp.net/

PEInAzure-CloudAddress

The UI dates from Silverlight 2 (our first Silverlight release). We’ve ported it forward to DevForce 2010 and Silverlight 4 but haven’t touched the XAML. Pretty ugly but it gets the point across. Some day, some day …

Prism Explorer, aside from showing that DevForce and Prism play nice, demonstrates a variety of DevForce features such as:

  • Arbitrarily complex queries, including anonymous projections
  • Add, delete (enabled for Customer only in this case), and save
  • Integrated validation (e.g., Customer requires a city)
  • Lazy and eager load of related entities
  • Online and offline (toggle “Connect” button)
  • Save and restore entities to isolated storage file
  • Out of browser

Here it is, running Out-of-Browser, after querying for “Customers (and their orders) starting with C”

PEInAzure_CustWithC

Here’s another moment in the life of the UI – queried for all Employees and clicked Edit button on good ole Nancy Davolio:

PEInAzure_EmployeeEdit

I shot video of Kim and me deploying it. Raw footage is 40 minutes, much of that watching it build on my stressed-out notebook (Camtasia and VS competing for cycles). Hope to get it to 20 minutes after cutting out the dross.

Still, I was amazed to get this done in 50 minutes of clock time (paused video 10 minutes while publishing to Azure staging ). That includes commentary, fumbling, and miscues.

More on all of that in my next post.

Friday, August 6, 2010

DevForce in the Cloud: 1st Flight

Our first Azure DevForce “application” debuted today.

DevForceInAzure-1st_Flight

Sure it’s just Northwind customers in an un-styled, read-only Silverlight DataGrid. Kind of like putting a monkey in orbit. But it’s an important step for IdeaBlade and DevForce … and I’m feeling a wee bit proud.

Behind that simple (simplistic?) exterior are DevForce 2010, SQL Azure, Windows Azure, Silverlight 4, Entity Framework v.4, and .NET 4. That really is EF 4 running in the cloud, not on the client as it is in most Azure demonstrations. That really is the DevForce middle tier “BOS” in the cloud and a DevForce Silverlight client executing in your browser.

We’ll probably have taken this sample down by the time you read this post. But who knows; if you’re quick, you may still be able to catch it at http://dftest003.cloudapp.net/

Kudos to Kim Johnson, our ace senior architect / developer who made it happen. Thanks to Microsoft’s Developer Evangelist Bruno Terkaly who first showed us EF 4 in Azure when there were no other published examples.

I’ll be talking about DevForce and Azure much more as our “DevForce in the Cloud” initiative evolves. It’s clearly past the “pipe dream” phase and I anticipate acceleration in the weeks ahead.

Those of you who’ve been wondering if we’d get there (Hi Phil!) or whether to "play it safe" and build your own datacenter (really?) … wonder no more!

ObservableCollection / DataGrid Memory Leaks

Ran into a BEAR of a memory leak today. Or, rather, one of our customer’s did … while investigating our PrismExplorer sample that demonstrates DevForce 2010 and Prism v.2.2 playing well together.

This post is a re-post of my exchange on our IdeaBlade Forum. I figure it’s worth repeating here should you run into it and not think to look on our forum.

The lesson, I hasten to add, is for all Silverlight developers. DevForce entities are not the cause. If you bind a Silverlight DataGrid to objects that implement INotifyPropertyChanged, this post is for you.

The takeaway is this: Don't reassign the ObservableCollection<T> bound to an ItemsSource; repopulate it!

An now … the story. First, the customer reports a problem

When ever I bind a datagrid or listbox via a ViewModel to an ObservableCollection(results) in a Callback method from a simple query … I end up consuming memory which will never be released, … not after disposing of the EntityManger, View, Viewmodel, etc. This behavior can be reproduced in your Prism Explorer when querying Customers, Orders, and back a few times. You can see this in Performance Monitor (perfmon) under process->private bytes where the count keeps climbing up.

Here is my response:
-------------------------------------------------------

You are (mostly) correct and oh ... how awful!

As I demonstrate below, memory is recovered when you clear the EntityManager. It would be recovered if you disposed of the EntityManager itself. I'm not sure why you didn't see these effects.

However, you are absolutely right that something horrible is happening. I spent much of the day researching it.

The only good part of the story is that it has nothing to do with DevForce. The cause is something in Silverlight, probably in the Silverlight DataGrid.

I will explain but it will be a bit of a journey leading ... ultimately ... to a sad-but-necessary workaround.

If you want to skip the journey and go right to the destination, the lesson for your code is:

Don't reassign the ObservableCollection<T> bound to an ItemsSource; repopulate it!

And now ... my sad tale ...

The main "ModelExplorer" view binds a Silverlight DataGrid.ItemsSource to the QueryResults property of the supporting ModelExplorerViewModel (the VM).

"QueryResults" is defined as IList but is always an ObservableCollection<T> in practice (henceforth written as "OC<T>").

The problem starts with the repeated resetting of the QueryResults in the ModelExplorerViewModel after every query.

A peculiarity of PrismExplorer (PE) is that the main "ModelExplorer" view could be asked to display objects of any type in the DataGrid. That's its purpose as a demo screen. Your grids typically only show one kind of object. But PE must work with arbitrary query result types.

Because those types change, the OC<T> must change to match type.

The obvious thing to do was craft a new OC<T> after every query ... one designed for the query results type, assign that new OC to the QueryResults, and raise PropertyChanged on "QueryResults". The DataGrid dutifully hears the call and refreshes its display.

Unfortunately, it consumes an extra 300K every single time. "300K" is not a misprint.

Here's the code with the garbage collection call and logging (aside: we now inject ILoggerFacade into the VM now so that we can write to the Visual Studio Output window).

    public IList QueryResults {
get { return _queryResults; }
set {
_queryResults = value;

Log("=== Total Memory = " + GC.GetTotalMemory(true));

RaisePropertyChanged("QueryResults", "QueryResultsCount");
SelectFirstQueryResultsItem();
}
}

If you add this instrumentation, query for "All Customers", and click the "Query" button repeatedly, the Output window will show that your memory consumption is climbing ~300K each time. Here are actual measurement.

Prism Explorer: "=== Total Memory = 3406212";
Prism Explorer: "=== Total Memory = 3914916";
Prism Explorer: "=== Total Memory = 4336668";
Prism Explorer: "=== Total Memory = 4756884";
Prism Explorer: "=== Total Memory = 5177356";
Prism Explorer: "=== Total Memory = 5782900";
Prism Explorer: "=== Total Memory = 6202860";
Prism Explorer: "=== Total Memory = 6616220";
// Cleared the EntityManager
Prism Explorer: "=== Total Memory = 3655320";
Prism Explorer: "=== Total Memory = 4076292";
Prism Explorer: "=== Total Memory = 4498300";
Prism Explorer: "=== Total Memory = 4918260";
Prism Explorer: "=== Total Memory = 5358912";
// Cleared the EntityManager
Prism Explorer: "=== Total Memory = 3655384";

Note that DevForce isn't going anywhere. You are issuing the same query repeatedly and DevForce satisfies it from the EntityManager cache. However, the PE ViewModel is building a new OC<Customer> each time and reassigning QueryResults. The DataGrid is rebinding the ItemsSource to the new OC<Customer> each time ... and chewing up memory each time.

If we comment out "_queryResult = value", DevForce and PE will continue to do their things ... DevForce may query the database or satisfy from cache if it can. PE will always build a new OC<T>, assign QueryResults with that OC<T>, raise PropertyChanged, stimulate the DataGrid to rebind to the QueryResults. Exactly the same code paths.

The only programmatic difference is that QueryResults always returns the exact same (empty) object.

The memory consumption goes flat ... as it should.

Of course it climbs modestly when you issue a query that fetches new data; that is to be expected. Press "Clear" to clear the EntityManager cache and memory is recovered.

This is proof enough for me that the memory leak is in Silverlight ... perhaps in the Silverlight DataGrid. Our entities are involved in some way ... that's why clearing the EntityManager cache allows the GC to recover memory. But the DataGrid is clearly chewing up memory at a fast clip without our adding any new entities to memory.

What could possibly take 300k? The entity data involved are miniscule (it's Northwind! 7 Employees ~90 customers). All entities combined do not weigh 300K.

The memory consumption grows by 300K when there are no new entities. Evidently Silverlight or OC is in a deadly embrace with the entities that prevents garbage collection (there are events involved). But even if so ... the numbers are staggering. We aren't adding 300K of new data each time we click the button. You can't write enough event handlers to consume 300K. The cost of an OC isn't 300K.

In my research, I tripped over an old WPF blog post (can't find it now) that said something about WPF creating completely new data and control templates for each OC. Now THAT is a fast way to burn memory. I'm betting that Silverlight is creating and caching a complete visual representation of the DataGrid and the associated entities each time I reset the ItemsSource with a new OC<T>!

I tried a number of things to shake up the binding ... anything to make it let go of whatever it was holding:


  • clear the _queryResults ( _queryResults.Clear() ) before re-assigning it with the new OC


  • clear the _queryResults and set it null before re-assigning it with the new OC


  • clear the _queryResults, set it null, raise PropertyChanged ... then assign with new OC

None of these attempts worked. Only pressing "Clear" worked.

What to do? The obvious answer is reuse the OC ... and that is the lesson for your application: Don't reassign the ItemsSource; repopulate it!

Of course OC<T> requires strongly typed contents. I tried OC<object> with the intention of simply clearing and refilling it with new results after each query. That executes without error. But it doesn't show anything on screen either ... pretty useless :-).

It actually worked if I use List<T> instead of OC<T>. But then I wouldn't have the benefits of ICollectionPropertyChanged and I'd have to manage adds, removals, clears by hand. Yuck.


The WorkAround

As a last resort, on each pass I check to see if the type of the fresh results matches the element type of the OC. If it does, I can re-populate the OC. If it does not match, I have to replace the ItemsSource with the new OC ... and pay the 300K tax.

If you always query for the same type, you'll be fine. You can change the query itself - there are numerous Customer and Employee queries in PE - without paying the tax. It's changing the result type that incurs the tax.

I tried to be clever and keep a dictionary of previously used OC types. If I was querying customers, I'd pull out the OC<Customer>; if I was querying employees, I'd pull out the OC<Employee>. That didn't help. The DataGrid doesn't remember OCs that it has seen before. Re-using old OCs didn't change its penchant for devouring another 300K

So all I can do is slow it down. If PE starts to blow, you can "Clear" the EntityManager and it will recover.

Here's the revised code (which will appear in the next PE release, minus the GC & Log calls)

    public IList QueryResults {
get { return _queryResults; }
set {

ResetQueryResults(value);

Log("=== Total Memory = " + GC.GetTotalMemory(true));

RaisePropertyChanged("QueryResults", "QueryResultsCount");
SelectFirstQueryResultsItem();
}
}


private void ResetQueryResults(IList results) {

if (null != _queryResults) _queryResults.Clear();
if (null == results 0 == results.Count) return;

var resultsType = TypeHelper.GetItemType(results);

if (_queryResultsElementType == resultsType) {
// Same results collection type; can refill it
foreach (var item in results) {
_queryResults.Add(item);
}
} else {
_queryResults = results;
_queryResultsElementType = resultsType;
}
}

private Type _queryResultsElementType;

Here are memory reports:

// Query for All Customers

Prism Explorer: "=== Total Memory = 3411896"
Prism Explorer: "=== Total Memory = 3425356"
Prism Explorer: "=== Total Memory = 3416064"
Prism Explorer: "=== Total Memory = 3416076"
Prism Explorer: "=== Total Memory = 3416076"
Prism Explorer: "=== Total Memory = 3429460"
Prism Explorer: "=== Total Memory = 3416076"
Prism Explorer: "=== Total Memory = 3415020"
// All Employees
Prism Explorer: "=== Total Memory = 4203344"
Prism Explorer: "=== Total Memory = 4212964"
Prism Explorer: "=== Total Memory = 4213000"
Prism Explorer: "=== Total Memory = 4213000"
Prism Explorer: "=== Total Memory = 4213000"
// Clear Entity Cache ... followed by All Employees
Prism Explorer: "=== Total Memory = 3706416"
Prism Explorer: "=== Total Memory = 3588660"
Prism Explorer: "=== Total Memory = 3593996"
// First Employee
Prism Explorer: "=== Total Memory = 3590928"
Prism Explorer: "=== Total Memory = 3604372"
Prism Explorer: "=== Total Memory = 3589676"
// Employees named Smith (there are none)
Prism Explorer: "=== Total Memory = 3605584"

// All Employees (again)

Prism Explorer: "=== Total Memory = 3757472"
Prism Explorer: "=== Total Memory = 3762120"
Prism Explorer: "=== Total Memory = 3770336"
Prism Explorer: "=== Total Memory = 3762144"

Friday, April 30, 2010

Context for Comparing DevForce, CSLA, and RIA Services

I recently posted on some important differences between DevForce and RIA Services. Someone posted a comment to the effect that DevForce and CSLA seem to be the same and invited me to comment.

I see the similarities between DevForce and RIA Services. I don’t think DevForce and CSLA are alike at all. Why would someone suggest that they are?

That got me thinking and lead to this post which reframes the question.

It first establishes what we have in common … and how to decide quickly if you should consider any of us … or none of us … for your application project.

Then it articulates fundamental criteria for comparing the three.

Important: These criteria are not evaluative. They are as neutral as I can make them. I feel pretty confident in that neutrality because, as I apply them to the three products, I can not tell which one of them is “better”. They help me organize my thoughts, not decide which one is “right.”

Let's start with the what we have in common.

DevForce, CSLA, and RIA Services target the same problem: building distributed business applications from end to end, server to client.

If you don't think you have this problem, none of us are right for you.

We offer .NET-only products. RIA Services is limited today to Silverlight applications; DevForce and CSLA support most .NET client technologies (I don't think any of us are ready for WP7 .. yet. CSLA may work on the CE; we do not). Your required server and client operating environments may make the choice for you.

We all have the same presumption of a relational database as the primary backing store. Sure we can also persist to other backing stores. But these alternatives appear in supporting roles if they appear at all. None of us are your best choice for building applications that primarily access data through messaging services or persist to one of the NoSql schema-less data stores.

We all attempt to solve your application problem within some flavor of "mobile business objects" paradigm. If you summarily reject a "mobile business object" solution on principle, none of us are right for you.

Finally, we are all framework products. We're not application generators. If you want to drag-and-drop your way to a finished product, we're not for you. If you reject 3rd party frameworks, we are not right for you either.

With me still? Because now we are ready to differentiate the three products.

You have looked at the problem and you've chosen to solve it by allocating some responsibilities to a framework, reserving others for yourself in the expectation that you will be writing custom application code.

Every framework is opinionated. Each says:

  • We will be responsible for these tasks (the A-list).

  • You will write custom code for these other tasks (the B-list).

  • Our architecture and recommend development practices pretty much prescribe that you will write your custom code in manner C.

You look at these opinions and ask yourself

  • Do I want the framework to do the things on the A-list?

  • Do I want to write code for the things on the B-list?

  • Do I want to develop in manner C?

  • How productive will I be if I adopt this framework?  How quickly can I write quality B-list code when I adopt manner C?

  • What items on the A-list do I really have to do myself? Can I take these particular tasks away from the framework with acceptable ease and still, in the main, be using the framework the way it was intended?

  • I wish some of the items on the B-list were handled by the framework. What will it take for me to write them myself or acquire them from someone else?

  • I don't care about some of the items on the A-list; do these items get in my way and if so, will that be a serious problem?

  • Do we have the skills and development culture to use this framework effectively? If not, can we and should we acquire those skills?

  • How do these factors collectively influence my development timeline? Do I have a deadline? If so can I reasonably expect to hit the deadline with the resources I have using this framework?

You will also consider some “non-functional” factors

  • Product quality and maturity
  • Access to source code
  • Support
  • Influence on roadmap and repairs
  • Product release schedule
  • Community (resources, training, etc.)
  • Company stability

I have conspicuously omitted one factor: license costs. CSLA and RIA Services have no license costs. DevForce does. Why doesn’t that matter?

It doesn’t matter because you’re building a custom application that you’ll be living with for years. A few thousand dollars of licensing fees are irrelevant … they are rounding error … compared to the application investment you’re about to make and the risks you are about to assume.

If this is not blindingly obvious to you, you shouldn’t be making this decision. You simply don’t have the requisite business acumen to make the right choice.

When you dissect the products according to these criteria – which you’ve refined and weighted to suit your business environment  and requirements – the differences among CSLA, DevForce, and RIA Services will stand out in sharp relief.  You will have a foundation for choosing among them.

I said the differences will be stark; I didn’t say that the choice will be easy. Even within the same organization people will weigh some differences more heavily than others.

You will at least have arranged matters so you can see more clearly what you’re arguing about.

Wednesday, April 28, 2010

DevForce Or RIA Services?

I’m thrilled RIA Services is out at last.

Developers who are familiar with Forms-over-Data, end-to-end, business application development at last have a Microsoft-sanctioned approach to building such applications in Silverlight.

They’re less inclined to roll-their own data management solution and more inclined to let someone else handle the plumbing.

That choice is not without problems. It’s unnerving to hand the keys over to a framework and say “you drive.” But let’s face it, your home-brew solution is just another framework too. It may be yours … which makes you feel all gnarly and in control. But it’s still a framework that someone is going to have to document, train, maintain, support, and grow … at the probable expense of delivering the end product demanded by the customer.

RIA Services has made it OK to delegate these challenging and time-wasting aspects of the application to a third party.

For me, the usual conversation has shifted from “Why do I need something like DevForce?” to “Why DevForce instead of  RIA Services?”

Here’s how someone put that question on the RIA Services Forum.

DevForce or WCF RIA Services? Both seem to do more or less the same data abstraction for Silverlight, but which would be the better route to go in the end? The price tag for me is the winner with WCF RIA services, but this is not always the right choice. Any thoughts?

Colin Blair, MVP and RIA Services aficionado, invited me to respond to that forum post. Which I was happy to do :-).

You could read it there. But I’ll spare you the trip and re-post my response here.

I have much more to add… and I’ll elaborate in the coming weeks and months. Meanwhile, it’s a start.

--------------

Yes, RIA Services and DevForce share a common perspective: end-to-end application development, programming against a rich entity model backed (typically) by relational data with validation, concurrency, security, change management, unit-of-work rolled in.

DevForce has been in commercial release since 2002 (long before Silverlight) so it's been dipped rather thoroughly in the acid bath of real world experience.

It supports both 2-tier and n-tier applications (a config change) and all the typical .NET client technologies: Windows Forms, WPF, Silverlight, ASP Web Forms, ASP MVC. You can write one code base and use it across all of them ... not that that is always a great idea. We have versions for .NET 2.0, 3.5 and 4.0.

Let's assume, however, that you are only interested in Silverlight and you don't care about product maturity, track record, or any of that.

If it seems that DevForce and RIA Services are similar ... that's intentional. We have a common perspective and we want DevForce to align with RIA Services APIs and techniques as much as possible ... so that it's easy to move between the two communities.

But DevForce and RIA Services are not clones. We do many things differently and offer capabilities beyond the RIA Services baseline.

Our customers often cite some of the following dozen DevForce differences as their reasons for choosing DevForce:

1) Same model on server and client. The code you write on the server is the same as the code on the client (unless and except where you don't want it to be). Open the Employee class on either side ... it's identical. The physical class file resides on one side (typically a server, full .NET project) and you have a Silverlight model assembly that links to that file. Compilation produces different assemblies (.NET and Silverlight) whose class names, structures, and logic are effectively the same.

2) No code generation magic.  We don't touch your code. We don't generate client code. No surprises.

3) Most DevForce applications use Entity Framework for Object Relational Mapping (ORM) and persistence operation (query, insert, update, delete).

DevForce generates its own (partial) classes from EF's EDMX using T4 templates; we don't need, use, or generate EF's own classes.

Our classes are serializable and designed to support RIA scenarios. We inscribe the UI-hint attributes (e.g., Display) and the obvious validation attributes (e.g., Required) into the generated classes. No separate metadata class files needed (keep reading)

4) You can override our code generation to introduce your own behaviors. You could take over the entire template but it's much easier to override one of the many code generation methods that target the moment of interest to you (e.g., property generation).

5) No service method pollution.  In RIA Services you have CRUD methods for each type in your model. There could be 400 methods in a 100 entity model. We don't generate CRUD methods; like WCF Data Services, we manage CRUD operations dynamically. Of course you CAN write arbitrary service methods if you wish. You can intercept any Query to inspect, limit, adjust the query. You can intercept any Save to inspect, reject, add/subtract/modify the entities in the change set, or perform arbitrary operations (custom logging and auditing).

6) Iterative Development: In demos, you build your model and you're done. In reality, you will add, remove, and rename your properties, entities, and the relationships among them. over the long course of your application's lifespan. Such adjustments are trivial with EF-backed models; update the EF model, compile, and run.

Ok ... maybe you should test too and you made these changes because you wanted to introduce new capabilities. The point is that you'll program to those business concerns; you won't be updating a domain service file and fixing up satellite, entity-related class files.

7) Client-side LINQ. DevForce supports client-side composition of any LINQ to Entities query, including projections of all kinds, projections into anonymous types, aggregations, grouping and ordering, includes, polymorphic queries (query on a base type). There is NO query you have to compose on the server in a "domain service" method. You don't add OrderBy clauses on server query methods. It is almost unheard of for a DevForce application to have a server-side query method.

8) Client-side caching. Query results are cached as are entities you create, modify, delete ... and have not yet saved. RIA Services does this too.

But DevForce applies your LINQ queries BOTH to the server store and to the cache. Suppose you have queried for all Northwind employees; you change "Nancy Davolio" to "Sally Davolio" and you add a new employee named "Sam". Meanwhile, another user has saved a new employee named "Sherry". What is the result of a query for employees with first name beginning "S"? The DevForce answer includes "Sally (formerly Nancy)", "Sam" and "Sherry".

You can tell DevForce to query ONLY the cache or ONLY the server ... as appropriate.

It's trivial (and recommended) in DevForce for your Silverlight application to prepare the cache with entities you need for a particular user scenario as you enter that workflow. You then would default subsequent query execution to "CacheOnly", and "party on" as if you had an in-memory database. Yes, you can still make remote queries and asynchronously refresh all or part of the cache at will.

The key benefit: you can easily program the user experience in the synchronous style familiar to most business application developers and still exploit the responsiveness of asynchronous data access ... using the same queries.

9) Productivity and Testability. You don't need a database or server to build and test your application. You can populate the DevForce entity cache with test entities - entire object graphs - and run disconnected. You can serialize the cache to file (e.g., Isolated Storage) - in a single method - and restore that cache at will. I often build a development data cache file, include it as a resource, and launch my application "in test mode"; the cache fills with the dev data rather than having to hit the server, and I'm running with no web server at all. I can make and explore UI changes in a fraction of the time it would take if I had to spin up Entity Framework and a server. I can work with colleagues far away who don't have Entity Framework or the database ... because there is no dependence at all.

10) DevForce entity properties are implemented with "property interceptors" that enable you to inject custom behavior into the getters and setter. Without touching the Employee class I can add logic to automatically mask the Social Security number  ... unless the employee is the current user or the user is an HR admin. I could inject logic into a setter to force values to upper case. I have complete, fine-grained control of the DevForce generated properties before and after the actual value access or mutation.

11) DevForce validation supports the same DataAnnotation validation attributes as RIA Services in addition to our own (richer) validation attributes. But you're not limited to attributes. You can add validation rules programmatically to the class and we'll discover them. You can access the list of validation rules for any type and manipulate that list, removing existing rules and adding other rules ... perhaps customer-specific rules determined by metadata. You can do this with logic entirely outside the entity class. And DevForce validation can be applied to any object, not just entities.

12) Navigation properties (Order.OrderDetails, Order.Customer) to related entities work even if the related entities are not in cache. DevForce fetches them asynchronously ... and can notify you when the data arrive. I would be wary of multiple, hidden trips to the database (the N+1 problem with lazy loading); you should consider eagerly loading these entities instead. But lazy loading has its place. Of course you can disable lazy loading of any property at any time.

You can find out more for yourself by visiting our web site, http://www.ideablade.com or write to me at AskWard@ideablade.com.