Rants Tagged with “.NET”

As my continued facination with all things SQL Server Modeling related, I was tasked with writing a short article on the introduction of the basics of SQL Server Modeling for the developer. The result is the article "The Busy Developer's Guide to SQL Server Modeling" that was released on MSDN today. It is short so you can get the big details without investing a month learning the technology. Let me know what you think!
If you've been following my blog, you should know that I am keeping a pretty close watch on ADO.NET Data Services. The team recently released a second CTP of the new version with some interesting features. This CTP has some pretty compelling additions, but I am going ot focus on one in particular.
I've been teaching and using ADO.NET Data Services for a long time and I like showing off exposing a LINQ-based provider (Entity Framework, NHibernate or others) to a Silverlight application. While ADO.NET Data Services does expose its API through a REST API, the magic for me is in its use in Silverlight. In case you haven't been following along, using the Silverlight client you can issue a LINQ query through the Silverlight client (though in fairness, the full power of LINQ is not supported in the client):
var qry = (from g in ctx.Games
where g.Genre.Name == "Shooter"
orderby g.ReleaseDate
select g) as DataServiceQuery<Game>;
qry.BeginExecute(new AsyncCallback(r =>
{
try
{
theList.ItemsSource = qry.EndExecute(r).ToList();
}
catch (Exception ex)
{
// NOOP
}
}), null);
This is a powerful feature so that (unlike web services) developers can use a looser service definition to define their data stack. Let the developer who needs data be able to sort, filter and shape that data as necessary.
The last part of that phrase is "shape" on purpose. When I first teach this technology, I am often asked "what sort of shaping do you mean?" In ADO.NET Data Services 1.0, you could shape it by returning a hierarchy of data using the Expand method in the LINQ query. For example, we can return the game data with the Genre entity attached to every game like so:
var qry = (from g in ctx.Games
.Expand("Genre")
where g.Genre.Name == "Shooter"
orderby g.ReleaseDate
select g) as DataServiceQuery<Game>;
qry.BeginExecute(new AsyncCallback(r =>
{
try
{
theList.ItemsSource = qry.EndExecute(r).ToList();
}
catch (Exception ex)
{
// NOOP
}
}), null);
But this level of shaping is powerful but limited in scope. This is where ADO.NET Data Services 1.5 comes up trumps. In this new CTP we can now do projections to retrieve specific data. For example:
var qry = (from g in ctx.Games
where g.Genre.Name == "Shooter"
orderby g.ReleaseDate
select new
{
Name = g.Name,
ReleaseDate = g.ReleaseDate.GetValueOrDefault(),
}) as DataServiceQuery;
This query creates a new anonymous type that has the two values we want instead of returning the entire entity. In any other .NET project this would be fine, but for Silverlight we can't use the anonymous type for data binding (for security reasons). So like other anonymous type uses in Silverlight, you must project them into a known type. A type like that is pretty easy to cruft up if you need:
var qry = (from g in ctx.Games
where g.Genre.Name == "Shooter"
orderby g.ReleaseDate
select new GameInfo()
{
Name = g.Name,
ReleaseDate = g.ReleaseDate.GetValueOrDefault()
}) as DataServiceQuery<GameInfo>;
This is useful to no only limit the fields you return but also to shape the result. For example we can use the projection to retrieve the name, release date and the genre's name (normally a related object) like so:
var qry = (from g in ctx.Games
where g.Genre.Name == "Shooter"
orderby g.ReleaseDate
select new GameInfo()
{
Name = g.Name,
ReleaseDate = g.ReleaseDate.GetValueOrDefault(),
GenreName = g.Genre.Name
}) as DataServiceQuery<GameInfo>;
This is all well and good, but what about saving these projections? For the most part you should treat complex projections (like the one above) as read-only. But if you retrieve entities that are purely subsets of existing entities, then ADO.NET Data Services will handle it. Though currently this is crashing in Silverlight (it is a CTP after all). I will update this if I find a way around the saving bug in the near future and post the demo at that time.
But in general this is an awesome new addition to the library that I hope will close some of the use-cases that forced me to write Service Operations in the past.
What do you think?

It all depends...
I've spent the better part of six weeks building the new AgiliTrain website and its been quite a lot of fun. Of course if you have been reading this blog for long you know that I usually take a personal project like this as an opportunity to learning something new. In this case I did three things I haven't done on a personal project before:
- Use ASP.NET MVC (Beta)
- Use Oslo's MSchema
- Use a Designer
I've been itching to use ASP.NET MVC on a project but until the beta arrived I didn't want spend too much time with it. Of course as you probably know, ASP.NET MVC released a RC yesterday so its pretty close to being done. I am still on the Beta until they RTW (release to web) ASP.NET MVC. Don't want to retrofit it twice.
I've been thinking a lot about how I would characterize my experience with ASP.NET MVC. I recently was at a talk from Paul Lockwood (at the Atlanta .NET User Group) and he thought that it was two weeks of a steep learning curve then bliss. That's pretty close to my experience. I thrashed for a couple of weeks wondering whether going back to WebForms would be faster...but I was patient.
I talk to some people about their fears of ASP.NET MVC and the big one I hear is lost of ViewState. I was never a fan of ViewState and was always perplexed that most projects used WebControls and not nearly enough HtmlControls. HTTP is stateless so in many many situations remaining stateless makes more sense. Since the HTML controls were lighter weight I tended to use them much more often. That certainly makes my move to MVC easier as I am not bogged down by the loss of ViewState.
Another contention I hear is that ASP.NET MVC allows you to write code more like the web. This means doing a lot of AJAX and using jQuery (or Dojo, or whatever you want) as your UI layer. While that is interesting in a wide variety of scenarios...I don't think PostBacks are as evil as we make them out to be. One of the problems with WebForms was that since it was tied to post-backs and sending back ViewState...those post-backs were always big. For AgiliTrain I didn't feel the need for a lot of wiz-bang. I am just presenting materials and taking data (for registration and such). Very simple and doing that in simple HTML still appeals to me. In fact, the argument against simple post-backs is lost without ViewState. My Postbacks to the server are tiny because they simply contain mostly just the data users are entering. I think the real evil was when post-backs were used as a replacement for event handling situations...the post-backs themselves weren't the problem...the programming model was.
I did use jQuery in a couple of places where I needed rich behavior in the UI but that was the exception rather than the rule. I built a website not a web application. If you're building a web application, this is likely to be reversed. Building lots of interactivity and paging and such makes sense in that case...just not mine.
But why did I use ASP.NET MVC at all? Was it because I wanted to learn a new technology or was it the best tool for the job? In my case both are true. I needed a site that is very SEO friendly and to do the kind of routing I wanted (like I did in my Wildermuth.com site) was harder than it should have been. I wanted a better experience. I also thought that since I was presenting information that is changing somewhat rapidly that I could develop it faster with ASP.NET MVC. Not faster in the initial implementation (because I had to learn MVC) but faster to add new functionality as it required it. I am not positive this is true but in the last few days I've been able to add new pieces of functionality to the site pretty easily. It feels a lot more modular than my other sites.
There were two big ah-ha moments for me in using ASP.NET MVC:
- When I was told to create models that contained the data for the view (instead of using my data model).
- When I integrated the designer's wireframes into the project.
The first of these was big because I was using ViewData for everything and it felt like Session state again. A big property bag of loosely typed data that I was hoping would work.
The second of these was a huge surprise as the MVC code was mostly clean HTML (no magic ClientID's or controls) so that integrating was simple.
In the next couple of parts of this series I will delve deeper into how I built up the site using ASP.NET MVC and why I think its a great approach for my future projects.
If you missed me in Bulgaria's DevReach conference, the video of my Silverlight Data Access talk is now available. The original talk's description was:
In this session, we will explore the different methods for dealing with data in your Silverlight 2 applications including LINQ, ASMX, WCF, REST, Astoria and WebClient calls. The session covers both how to consume data as well as how to expose data to Silverlight 2.
Hope you enjoy it!
I am working on a hybrid ASP.NET MVC and MVC Dynamic Data project. To work on it I started with the MVC Dynamic Data project assuming this would be a Dynamic Data Project and an MVC project. As Scott Hanselman recently posted, you can mix and match pretty easily so the code was working but I was missing an important piece of functionality in Visual Studio:

My project wasn't being showing these items (or other menu options specific to MVC apps). I suspected it was some magic in the project file so I opened it up in my favorite editor:
<Project ToolsVersion="3.5"
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">
Debug
</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F7526D86-12B4-434F-8355-20592CFC4937}</ProjectGuid>
<ProjectTypeGuids>
{603c0e0b-db56-11dc-be95-000d561079b0};...
</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Foo.Web</RootNamespace>
<AssemblyName>Foo.Web</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
The missing bit was a special ProjectTypeGuid: {603c0e0b-db56-11dc-be95-000d561079b0}. You need to add this to the existing ASP.NET project's ProjectTypeGuid list in the project file and magically the project item types appear.
HTH
Today at 3pm CST (4pm EST, 1pm PST) I will be doing a LiveMeeting talk on ADO.NET Data Services. If you are not at the PDC this week, drop by NotAtPDC.com and check out my session!
I haven't had a chance yet to drop in on the ALT.NET Meetup but i'll be there this Wednesday. If you're interested in pragmatic development or just want to listen in on some of the ideas surrounding ALT.NET, go RSVP and join us at the meet up. As a bonus its a "Thinking Man's Tavern" in Decatur which is a cool little cafe with kick ass food.
Will I see you there?
There is a known problem with ADO.NET Data Services today that is important if you (or your server) lives in specific timezones. The problem is associated with the way that the Silverlight Data Services Library constructs their URI for searches.
The problem surfaces if you do a query that has a DateTime comparison in it. For example:
var qry = from o in ctx.Orders
where o.OrderDate <= dt
select o;
This query generates the following URI in the EST timezone in the US:
http://.../ProductService.svc/Orders()?$filter=OrderDate le datetime'2008-10-13T00:00:00-04:00'
This works great. The problem is that in other timezones (e.g. Bulgaria) where its forward of Greenwich Mean Time, so the UTC date is +03:00 like so:
http://.../ProductService.svc/Orders()?$filter=OrderDate le datetime'2008-10-13T00:00:00+03:00'
Because the "+" isn't URL Encoded, it becomes a space which makes the date incorrect. For now you can convert the date to universal time but that's a hack at best:
var qry = from o in ctx.Orders
where o.OrderDate <= DateTime.Today.ToUniversalTime()
select o;
It works but its a hack.
In building my Silverlight RC example using ADO.NET Data Services for Entity Framework and NHibernate I ran into what I think is a common pattern. I am writing an editor for XBox game data. The model for this data uses decorator tables in the database which are modeled as a common "Product" class and derived "Game", "Console" and "Accessory" classes. In the application I am using paging to only look at fifty results at once. This works fine on both sides.
But one of the pieces of information I wanted was a list of all the Game Genre. This became problematic as ADO.NET Data Services wanted me to retrieve all 880 games in order to get a list of these Genres (of which there are only 20 some odd). The whole idea of using paging is go avoid the huge overhead of bringing down the whole entity. Interestingly when I executed a LINQ query that used projection into non-entities, the query wasn't supported as projection isn't allowed in the ADO.NET Data Services URI model (which the client uses).
What ADO.NET Data Services does allow is to create Service Operations (e.g. WebGet or WebInvoke) on the Data Service to extend the model for specific cases. There are some limitations (must return IEnumerable<T>, IQueryable<T> or void) but this works pretty well. The difference between returning IEnumerable and IQueryable is whether system queries can be applied to them. Returning a fixed list (my need) meant to return a IEnumerable<T> list. Intersting that ADO.NET Data Services support returning an IEnumerable<T> of primitive types. For example my operation was spec'd as:
[WebGet]
public IEnumerable<string> Genres()
{
}
This works and returns a simple XML file with the primitive values. But alas the Silverlight Data Service Client doesn't support non-entities. I tried using the DataServiceContext.BeginExecute() to call this service and it threw an exception that it couldn't materialize non-entity classes. Hrmph!
This was a case where adding a quick web service call to get this data on the server and return it would have been the easy road, but that's not how I roll, is it?
After confirming this behavior with the Data team, I decided to write an extension to the DataServiceContext class to support this. In this little piece of code, the same pattern of calling DataServiceContext.BeginXXX is used. To make this work I simply use the HttpWebRequest class to do a simple GET to the server's URI syntax and use LINQ to XML to convert the data into the simple types (String in my case).
I've started to help out with some new ideas on the CodePlex SilverlightContrib project so I thought this was the perfect place for this code. Its not packaged up yet in a build (and probably won't be until sometime after RTW ships) but if you want to grab it you can grab the latest checkin I made:
SilverlightContrib ChangeSet 41005
I'll be shipping this new demo as soon as RTW ships (its not done yet). Look for the announcement here.