Archive

Archive for the ‘LINQ’ Category

A Good, practical LINQ example

January 17, 2008 14 comments

You may recall that one of my New Year’s Resolutions was to find and participate in a .NET Forum. Well, I have joined several, and have even posted a few times. While perusing the C# Corner forums today, I found this post about not being able to break out of a loop. The code was using one of my favorite techniques for Windows Forms, the ErrorProvider. I like ErrorProvider and use it quite a bit, and I have done what the poster was trying to do many times: loop through the Controls on a Form and find out whether any of them have an active error message. If they do, then I use that information to warn the user or set some Form state so that it is apparent that an error exists.

My answer does not specifically address the issue the poster brought to the table, but the post got me to thinking: we should be able to use LINQ to solve this problem. Here is a typical example of the loop construct:

bool hasErrors = false;
foreach (Control c in this.Controls)
{
    if (!"".Equals(errorProvider1.GetError(c)))
    {
        hasErrors = true;
        break;
    }
}

In looking at this, it appears we have a good case for using LINQ: we have a Collection and we want to query that Collection for information about itself. Seems it should be pretty straightforward, and ultimately it is, but in this particular case it took a little trial and error to hack it out. Since it wasn’t as simple as I originally thought it would be, let’s walk through it in stages.

Build a Queryable Object

The first step is to try and build a LINQ query of all the Controls on the Form:

var q = from c in this.Controls
        select c;

When I tried to compile this, I got an error I did not expect:

Could not find an implementation of the query pattern for source type ‘System.Windows.Forms.Control.ControlCollection’. ‘Select’ not found. Consider explicitly specifying the type of the range variable ‘c’.

Naturally, I reexamined the code and couldn’t find anything odd about it, but what did seem odd was that I knew this.Controls was a Collection, and LINQ is supposed to work on Collections, right? Wrong!

Getting a Sequence from a Collection

If you read my recent LINQ to Objects post you may recall that LINQ does not work on Collections, but rather Sequences. It soon dawned on me that ControlCollection does not qualify as a Sequence because it does not implement IEnumerable<T>, but rather IEnumerable. This led me to uncharted territory: how do I get an IEnumerable<T> from an IEnumerable? Well, there was definitely some trial and error, and a lot of IntelliSense browsing, but I finally figured out an elegant solution.

Microsoft was gracious enough to provide an IEnumerable extension method (my favorite new feature) that will cast an IEnumerable to an IEnumerable<T>. Fittingly, this method is named Cast<T>(). Here is the code that will transform our ControlCollection into a usable Sequence:

var q = from c in this.Controls.Cast<Control>()
        select c;

Now we have a LINQ query object representing all the Controls on our Form.

Querying the Queryable Object

Now that we have a Sequence instead of a Collection to work with, this could come in quite handy. In fact, this would be a good candidate for a ControlCollection Extension Method in its own right. In the meantime, now that we have a queryable object, we have several options for how to complete our task. One way is to query the entire Sequence when we need it. I’m going to use our friend the Lambda Expression to find out if there are any Controls with Errors in the errorProvider:

// Query as needed
MessageBox.Show(q.Count(c => !"".Equals(errorProvider1.GetError(c))) > 0 ? "There are errors!" : "No errors!");

Again we are using a supplied Extension Method called Count<>() and passing it a Func<> defined by our Lambda Expression. If the count is greater than 0, then we have errors, else we do not.

This approach is especially handy if you may need to query the list in multiple ways. In our case, however, we know that this criteria is the only one we will need, so we have the option to embed our Lambda in the LINQ statement itself. To do so, we will use yet another Extension Method called Where:

var q = from c in this.Controls.Cast<Control>()
        .Where(c => !"".Equals(errorProvider1.GetError(c)))
        select c;

You’ll notice that this is the same logic just implemented as part of the LINQ statement. Now our consuming code is a bit simpler because our list is defined as only the items with messages in the ErrorProvider:

// Now we don't need the Lambda
MessageBox.Show(q.Count() > 0 ? "There are errors!" : "No errors!");

Here is the complete code block:

var q = from c in this.Controls.Cast<Control>()
        .Where(c => !"".Equals(errorProvider1.GetError(c)))
        select c;
MessageBox.Show(q.Count() > 0 ? "There are errors!" : "No errors!");

Hopefully, as you experiment with these new features, you will come to appreciate how they all complement each other. This example turns out to be fairly simple, even though it took a little effort to work through. In it, we have taken advantage of Extension Methods, LINQ, and Lambda Expressions because they all work together. While these are all great additions on their own, the cumulative power they represent is outstanding. I guess .NET really is worth more than the sum of its parts.

Upgrade your C# Skills part 4 – LINQ to Objects

January 2, 2008 7 comments

If you’ve been following along recently, you’ll know that I have immersed myself in VS2008 and .NET 3.5. No discussion of these new technologies would be complete without addressing LINQ (Language Integrated Query). My problem is that LINQ has been written about to death by a lot of more qualified people than myself. With the other articles in this series I felt like I had something to offer, but here I am not so sure. So here is what I will do: I will hit the lowlights. Instead of showing you how to use LINQ, which you can get just about anywhere, I’m going to focus on when and why to use LINQ. I’ll also show you how to write your own Types that can be consumed by LINQ.

LINQ actually comes in five flavors:

  • LINQ to Objects – using LINQ to query Collections.
  • LINQ to SQL – using LINQ to directly query SQL Server databases.
  • LINQ to Datasets – using LINQ to query disconnected data stored in a DataSet.
  • LINQ to XML – using LINQ to create, read, manage, and query XML formatted data.
  • LINQ to Entities – using LINQ to query databases via the Entity Data Model Framework.

In this article, I will only cover LINQ to Objects as it provides the foundation for all the others. I will most likely cover LINQ to SQL and LINQ to DataSets in future articles. I have never been much of an XML user, but I may become one with the power of LINQ to XML: if I do, I will write about that at the appropriate time. Same goes for LINQ to Entities: the Entity Data Model Framework should be released sometime in the spring, and I will probably wait until then to cover that topic. So enough of me telling you what I’m not going to write about: let’s get to the real material.

IEnumerable<T>

I teach a weekly class on C# and .NET at my company to a group of procedural programmers, and every time I say something like “IEnumerable of T” I get back a bunch of blank stares. IEnumerable<T> is a generic interface that is implemented by every generic collection type in .NET. It is important to note that this is different from IEnumerator<T>, which we will not be implementing, at least not directly.

IEnumerable<T> is a pretty simple interface. In fact, it only exposes two methods, each called GetEnumerator() - one is generic and one is not. These methods return an IEnumerator<T>, which is just the default looping mechanism for the Collection. You’ll see this implemented in code later in this article.

For now, I want to stress that IEnumerable<T> is really what makes the magic of LINQ work. Anything that implements this interface (or one of its descendants) is queryable by LINQ. For a little terminology, we are going to use the term sequence to refer to anything that implements IEnumerable<T>. This is more accurate than Collection since there are Collections that do not implement this interface. So the answer to the question “When can I use LINQ to Objects?” is “You can use LINQ to Objects against any Sequence”.

Why use LINQ

So now that you know when you can use LINQ, lets talk about why using it is a good idea. Let’s revisit our old favorite, the Person class:

class Person
{
    public event EventHandler<maritalstatuschangedeventargs> MaritalStatusChangedEvent;
    private char _maritalStatus;

    public Person()
    {
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public string DOB { get; set; }
    public bool IsMilitaryVeteran { get; set; }
    public char MaritalStatus
    {
        get
        {
            return _maritalStatus;
        }

        set
        {
            if (_maritalStatus != value)
            {
                _maritalStatus = value;
                if (MaritalStatusChangedEvent != null)
                {
                    MaritalStatusChangedEvent(this,
                        new MaritalStatusChangedEventArgs("Marital Status is now " + _maritalStatus));
                }
            }

        }
    }

    public string GetFullName()
    {
        return string.Format("{0}, {1}", LastName, FirstName);
    }

    public override string ToString()
    {
        return string.Format("{0} {1}", FirstName, LastName);
    }
}

And let’s create a List of Person objects:

var people = new List<Person>()
    {new Person() {FirstName = "John", LastName = "Smith", DOB = "12/31/1968", IsMilitaryVeteran = true, MaritalStatus = 'M'},
     new Person() {FirstName = "Jimmy", LastName = "Crackcorn", DOB = "08/08/1934", IsMilitaryVeteran = true, MaritalStatus = 'S'},
     new Person() {FirstName = "Mary", LastName = "Contrary", DOB = "09/10/1957", IsMilitaryVeteran = false, MaritalStatus = 'D'}};

In a part 3 of this series on Lambda Expressions, we created a custom PersonCollection that inherited from List<Person> because we wanted to be able to filter these objects in specific ways. In that case, we were showing how to use a Lambda Expression with an Extension Method to loop through each Person that matched a certain Predicate<T> and perform some Action<T>. We initially did that by having the PersonCollection return another PersonCollection that was essentially a subset of the original. We could have also passed a more complex Lambda Expression that performed the filtering behavior for us as well as the Action.

In essence, though, the filtering done by the PersonCollection methods is a Query of the sequence. Rather than requiring a custom collection and predetermined methods, LINQ handles the query part for us. This buys us a couple of things. First, it means that we do not need a custom collection just to retrieve a filtered subset. Second, by not embedding this behavior in a Lambda Expression, we are substantively separating filtering behavior from actions on the filtered results. This means that both the filtering and the actions can be modularized.

Let’s look at an example:

var subset = from p in people
             where p.Age > 40
             select p;Console.WriteLine("Over 40:");

foreach (var person in subset)
{
    Console.WriteLine("{0} {1} is {2} years old. DOB: {3}", person.FirstName, person.LastName, person.Age, person.DOB);
}

If you compare these results to the list we created above, you’ll find that only the two over-40 objects are in the subset variable. This is what LINQ to Objects does for you: it allows you to query the Collection for a subset of objects. The resulting list is in fact an IEnumerable<T> for whatever type is in the Collection, so in this case we get back a list of Person objects. It also means I do not need access to the PersonCollection source code: I can execute LINQ statements over the collection directly, even if it is seaed, so I do not need to be able to create custom methods.

This is very powerful. Again, I’m not going to go over the mechanics of LINQ here, but suffice it to say that even this simple example should make you start to salivate. Imagine the possibilities! And it can be done with a very small amount of code.

Something more complex

As you may expect, the queries you write can be much more complex and functional:

var subset = from p in people
             where p.FirstName.StartsWith("J")
                && p.IsMilitaryVeteran
                && p.Age > 40
             select new {
                 LastName = p.LastName,
                 FirstName = p.FirstName,
                 Age = p.Age,
                 DOB = p.DOB
             };

There are some pretty cool things going on here that you need to be aware of. First, notice that I have complete access to all the members of the Person object in my query. Second, while a LINQ statement bears a strong resemblance to SQL, it is not SQL, so don’t judge it based on your SQL experience. Notably, it uses C# syntax and at first glance it appears backwards since the Select statement is last instead of first. This was done in order to support Intellisense, and Kathleen Dollard made a good point at a recent User group presentation: you may start to see SQL switch to this model (at least in the Microsoft World): wouldn’t it be nice to have full Intellisense support when writing SQL statements?

The third item of interest here is also in the Select statement. The first LINQ statement you saw returned an IEnumerable<Person>, but this one does not! In the select statement, we are actually creating an Anonymous Type by selecting only bits and pieces from our Person objects. In fact, these bits and pieces could come from multiple sources or be calculations or even new instances of complex types! This process of creating Anonymous Types from LINQ is known as Projection and it is very intriguing.

We discussed Anonymous Types and Compiler Inference in part 1 of this series, and now we see why they are so crucial. Without them, LINQ would be relegated to simply building subsets of Collections. With Projection though, LINQ becomes enormously powerful. Compiler Inference is used to create and build the Anonymous Type on the fly, and then is used again in order to loop through the newly created sequence. Without it, we would not be able to process the LINQ results, because in the case of projection there is no way to know the resulting Anonymous Type at design time.

Deferred Execution

I would be remiss if I did not at least point this out. A LINQ query is just a statement of execution: in other words, it is only a set of instructions concerning how to query a collection, it does not represent any data itself. No data is processed until the LINQ result object is referenced. This is called deferred execution, and you must be aware of it. If you do not understand this, “unpredictable results may occur”. Here is an example:

// Only define LINQ query - no data yet!
var subset = from p in people
             where p.FirstName.StartsWith("J")
                && p.IsMilitaryVeteran
                && p.Age > 40
             select new {
                 LastName = p.LastName,
                 FirstName = p.FirstName,
                 Age = p.Age,
                 DOB = p.DOB
             };
// "Subset" holds no data at this point

// Add new Person after LINQ query
people.Add(new Person() { FirstName = "Jill", LastName = "Upthehill", DOB = "12/31/1944", IsMilitaryVeteran = true, MaritalStatus = 'S' });Console.WriteLine("Over 40:");

// References LINQ query: NOW the data is gathered, so it includes the new Person
foreach (var person in subset)
{
    Console.WriteLine("{0} {1} is {2} years old. DOB: {3}", person.FirstName, person.LastName, person.Age, person.DOB);
}

Because the data itself is not read at LINQ definition time, it also means you can outsource the LINQ statements themselves to other classes and methods. Just be sure you return IEnumerable of Person:

public IEnumerable<Person> JVets(List<Person> people)
{
    var subset = from p in people
                 where p.FirstName.StartsWith("J")
                    && p.IsMilitaryVeteran
                    && p.Age > 40
                 select p;

    return subset;
}

Build your own Sequence

So far, we have been consuming known Sequences (such as List<Person>), but what if you wanted to perform LINQ over one of your own custom collection types? Hopefully by now the answer is obvious: you need to inherit from IEnumerable<T> or one of its children. The easiest way by far to do this is to inherit from one of the generic collections, such as List<T>. This would be my recommendation, but if you feel like getting into the nuts and bolts a little more, then you can implement IEnumerable<T> directly:

class PersonCollection : IEnumerable<Person>
{
    #region IEnumerable<Person> Members
    public IEnumerator<Person> GetEnumerator()
    {
        foreach (Person p in this)
        {
            yield return p;
        }
    }
#endregion

#region IEnumerable Members
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
#endregion
}

This is back to creating custom Iterators, which is beyond the scope of this article, but the magic here happens in yield return. This allows the collection to halt at each iteration and retain its position in the collection.

But here is the bad news: if you do this, you also have to implement all the Collection goodies, like Add(). This would be tedious and time consuming, and largely unnecessary since you could simply inherit from one of the Generic classes.

Conclusion

As stated at the beginning, this is not meant to be a LINQ primer. What you should get out of this is the following: you should use LINQ whenever you want to query collections. You can use LINQ to create collections of anonymous types, limiting the data and properties you have to deal with to just the ones you want. You can use LINQ to logically separate your queries from your actions.

And there is much more you can do with LINQ. You can aggregate results, join collections together, and so much more. Try it the next time you need to loop through a colleciton and pull out just certain objects. I think if you use it a couple of times you’ll find it becomes useful in a hurry.

Categories: .NET 3.5, C# 3.0, LINQ

Live Blogging VSLive! Austin – Day 4

November 15, 2007 Comments off

9:00am:

Just about to start a Post-Conference workshop entitled “Advanced C#: Moving up to LINQ, VS2008, and .NET 3.5″ by Richard Hale Shaw. Richard is extremely knowledgeable and has a tendency to go into deeper detail than anyone else, so this should prove to be a challenging class. Watch for updates throughout the day.

10:50am update:

Wow! I can’t wait to get my hands on VS2008 and .NET 3.5! Lots of stuff going on: we’ve been covering Custom Iterators again, which is pretty cool in its own right but has been around since 2.0. We’ve been covering them, though, in the context of Extension Methods which are HOT. Keep watching this site, you’ll see lots of stuff coming up in the future about Extension Methods.

I do have a couple quick bullets that came up:

  • DataContext is the key object type in LINQ
  • DataContext has a .Log method that will reveal the actual SQL that was executed
  • LINQ for SQL only works against SqlServer 2000+ : more evidence that we need to switch to SqlServer
  • Compiler Inference is very cool and reduces a lot of code. For instance: var allows the Compiler to infer the variable type from the return object and Anonymous Methods can be replaced with Lambda Expressions.
  • var will only work for local variables

1:30pm update:

Lambda Expressions are something else I’ll be exploring and posting about in the near future. Essentially, a Lambda Expression is a syntax method of creating Action<T> and Predicate<T> objects (there is another but I don’t recall its name). These objects are used by LINQ and some other constructs. Without Lambda expressions, these could be created using anonymous methods or by outsourcing the method call signature. Trust me, for most applications Lambda Expressions will be much better. There is too much about them to show how they work here, so here are a few bullets with the caveat that if you have not seen Lambda Expressions they won’t mean much for you:

  • Lambda Expressions can consume outer variables
  • Lambda Expressions can contain embedded code
  • Lambda Expressions can be used in LINQ or anywhere else that the return types are needed
  • Very readable, once you understand the syntax
  • Scope for Lambda variables is protected
  • Here is a sample line using a Lambda: .Filter( f => f.Length > fileSize )
  • In this case, “f” is a variable that lives only inside the (). “=>” is the Lambda Execution operator. “fileSize” is an outer variable (defined and populated elsewhere in the scope)

Other goodies:

  • Custom Iterators, and as such LINQ query objects, employ “Deferred Execution”. In other words, the actual IEnumerable<T> return value is not populated until the object is used (as opposed to when it is defined)
  • Extension Methods can be used in LINQ alongside the system defined actions
  • In VS2008, you can step through .NET Framework code in DEBUG (I believe there is an additional install to make this work)
  • LINQ can create Anonymous Types: in other words, the resulting IEnumerable<T> of a LINQ statement can be of a Type and structure that is not a defined type. This is very cool!
  • Properties in Anonymous Types can be based on Method call results
  • Properties in Anonymous Types can be named as desired
  • Properties in Anonymous Types can be other Complex Types

3:20pm update:

Lots and lots of details, and my seat is getting really sore, but I am here until the bitter end! Here are a few highlights from the last section:

  • LINQ sequences (Richard’s name for the resulting IEnumerable<T> collections) can be combined using .Concat() as long as the resulting Types are the same
  • This is even true for Anonymous Types: as long as they are defined exactly the same
  • LINQ can group results: this ends up in a IGroupedEnumerable that holds a set of Key Value pairs of the group key and IEnumerable<T>
  • The LINQ group feature can be based on an anonymous type (defined as part of the group statement)
  • Not LINQ related, but Richard mentioned something about using Partial classes as a way to protect custom code from Code Regeneration – great idea that also solves a problem I’ve had in my own CodeGen of ensuring that variables were defined as protected instead of private (since my system inherits from the generated abstract class) Update: I spoke with Richard after the workshop about employing this as a thin abstraction layer for DAL objects (Data Access Layer) and he suggested this would not be a good approach for that application.? And I may have misunderstood what he was saying in the first place, but I do think it led me to the idea that Partial classes could be a solution to this problem.

4:45pm update:

The last section was mostly about XLINQ (LINQ to XML), and we have plenty more to cover. The new XML classes are very easy to use and intuitive:

  • Essentially an OO wrapper around XML
  • XElement is the key class and represents an XML element
  • XElement has an “Elements” Collection of child XElement objects which is an IEnumerable<XElement>
  • This means that we should be able to use LINQ over the Elements collection

5:40pm update:

Down the home stretch. These are definitely long days, but well worth every minute.

I want to clarify something from above: the classes I mention for XML are XLINQ. These classes are found in System.Xml.Linq. After the XML is read in to these objects, then LINQ to Objects can be used as before. So XLINQ is LINQ, it just doesn’t look like the other flavors of LINQ.

Also, Richard showed a nice method of creating and storing much cleaner XML code based on defined classes behind the scenes. Then the Read and Write methods are abstracted out using Extension Methods and Generics. Very clean and powerful, and overall a fairly straight forward and simple approach.

Conclusions:

Well, this is the end of a great week. If you ever get a chance to attend one of these events, by all means you owe it to yourself to go. Here are the technologies I will be exploring in great detail as soon as I get back to the world:

  • LINQ – this is the KING of all the new MS technologies
  • WPF – simply awesome: a new paradigm in GUI design with great promise
  • SilverLight – a whole new web experience, both for developers and consumers
  • IIS 7.0 – looks substantially easier and more functional
  • Entity Data Model – not ready yet but will be soon and another paradigm shift
  • Visual Studio 2008 – should be RTMing this month. If you want to do any of the above, you’ve got to have the right tools.

I’m sure there’s more, but I am brain fried and butt dead. Check back often, I expect lots of new posts in the near future as I work through all this stuff.

Live Blogging VSLive! Austin – Day 2

November 13, 2007 Comments off

Keynote Address “Mapping your way through Microsoft’s Managed Data Access” – Michael Pizzo, Microsoft

10:30am:

The purpose of LINQ is to overcome some of the inherent flaws in Ad Hoc SQL data access from applications.

  • LINQ provides a set of language extensions
  • Integrates Query access as part of the application rather than implemented as Strings
  • Return values are in fact classes complete with strong typing rather than generic DataSets
  • Implements IQueryable to use LINQ over Collections
  • LINQ is available against DataSets, XML, and Entities as well as SQL

LINQ to SQL:

This is going to be the most important part of LINQ. This will essentially allow integration of the SQL Schema into usable objects in the Application.

  • Essentially a Strongly Typed SqlClient
  • Classes map to tables, views, SQL, and other Schema
  • Classes are generated by the LINQ Designer in VS2008 (saw a great demo of this)
  • Allows simple renaming of properties
  • Foreign Keys are implemented as Relationships
  • This means that additional table rows can be read in using Object syntax as opposed to additional SQL
  • Allows Type Inheritance for sub-Schema relationships
  • Can perform better than IDataReader
  • Can use StoredProcedures instead of SQL
  • Uses DataContext objects instead of IDbConnection – be sure to wrap in using statements for proper disposal
  • SQL Results become objects
  • Foreign Keys are available as Collections
  • DataContext has a .Log property for retrieving connection information
  • DataLoadOptions class allows finer control over when and how Related tables are read into the object

LINQ to DataSet:

  • DataSets still have value
  • Disconnected, serializable, etc.
  • LINQ makes filters, joins, projections, cross DataTable and cross Collection queries
  • Supports Typed and Untyped DataSets

ADO.NET Entity Framework:

The Entity Framework allows the Database Schema to be translated into complex Business objects.

  • Object Models are more complex than Schema’s rectangular storage model
  • Enables apps to work with higher level concepts such as relational navigation
  • Supports Type inheritance
  • Built over DataProviders
  • EntityClient is a declarative mapping of model to schema
  • LINQ can run over EntityClient
  • Produces Business objects
  • Provides Change tracking
  • Designers for this built into VS2008

The Future – Astoria:

  • Data Services over the web
  • LINQ/Query/CRUD over the web
  • Delivered as XML
  • Consumed over HTTP
  • LINQ can be used in Silverlight

11:40am update:

Attended “LING: What’s it all about?” by Ken Getz. I was really afraid that after the excellent keynote it would be repetitive, but NOT SO! I got so much out of it, and lots of it is not LINQ specific.

  • LINQ format is From… Where… OrderBy… Select
  • Select is always last, which really throws us SQL users
  • Select is last in order to properly support Intellisense (which unfortunately really only works in VB for now)
  • The From clause includes an item handle and indicates a Data Source
  • Uses implicit variable declarations – in both VB and C#, you can get an object variable to define it’s own type based on return value

Extensions Methods:

  • Add new methods to existing classes without access to the source code
  • Must be Public
  • Must accept a parameter of the type you wish to extend
  • In C#, it must be defined in a Static Class
  • C# uses the this keyword to indicate that this is an extension method
  • Can be used as a Static Class Method or an Instance method

Automatic Properties:

  • For properties that only expose an internal variable, the need to define and use that variable is no longer required
  • Does not require Constructors to update them, but it opens the problem of initializing properties that are not included in any constructor
  • SO – a Constructor can be used that does not actually exist: properties can be indicated on the new statement like so: MyClass c = new MyClass() {prop1 = value, prop2 = value};
  • Which means you can use a Constructor that essentially does not exist

LINQ for Objects:

  • Great for analyzing Collections
  • Takes advantage of Extensions Methods
  • Query class has many built in extensions:Any, All, Average, Where, Concat, Contains, Convert, Count, Distinct, Except, etc. etc.
  • Can use functions in Select clause
  • Functions must supply an expression (called “Lambda Expressions”)
  • Can include Anonymous Methods
  • Expressions can only have one item in and one item out
  • There can only be one expression on a function
  • Example: foreach(Actor a in Actors.Where(x => x.BirthDate.Month == 9))
  • “x” above is the individual object notation, “=>” indicates execute this comparison
  • Can use Anonymous Types – essentially, these are objects created on the fly (like creating columns in SQL Select) and added as a new Type to the resulting objects in the resulting Collection
  • Example: “Select new {NameOfProperty = actor.LastName + “, ” + actor.FirstName}”
  • Use Skip and Take to paginate different rows from within a collection

1:40pm update:

Attended “Styles and Data Templates” given by Bill Hollis. A good follow on from where we left off yesterday, the class got into some of the finer aspects of Templates and Styles. The more I see this stuff, the more I want to smack my head: I’ve had 3.0 installed since last year’s conference, but I’ve never forced myself to spend some time learning any of it. I look at it now and wish I had. But in truth this is the right time to be learning about it: with VS2008 and Blend, the technology is finally beginning to catch up with the theory. This is also the right time for my company given that we are just entering the development stage of a new suite of Applications. But enough rambling, on to the highlights:

  • Styles can be changed on the fly for any Element using the FindResource() method
  • TargetType is used to specify a style for all Elements of the same type en masse (within subsequent scope). This can be applied at any level, where ever a Resource can be defined (which is anywhere)
  • TargetType can only be applied to a single Type (this is not true for named Styles) – it cannot be found and applied to children of a different type
  • You can develop and import ResourceDictionaries to store Resources externally – think reuse, like importing CSS files
  • Styles support inheritance, so you can pull from a common parent and apply additional styles or override styles for specific elements
  • Style precedence is deermined from the element up, so if the element describes and style, then it overrides any named styles or TargetTypes
  • Inheritance accomplished by using “BasedOn={StaticResource parentStyleName}” on the Style definition
  • Styles can be tied to properties (and Events in WPF have reflecting properties, so by extension they can be tied to Events also)
  • DataBinding can be done at the Control or Container level, so you can specify a single Binding for an entire DataTemplate or Panel and then use it in child Elements
  • DataTemplate is like a mini-Window defined in XAML
  • DataTemplate places content in a ContentControl
  • The root Element is usuallya Panel, but can be anything
  • Anything goes regarding layout with a DataTemplate
  • Blend has a DataTemplate editor (why doesn’t VS have some of this stuff?)
  • A DataTemplate can have Triggers that change aspects of its display based on events and properties
  • They can be applied base don individual properties to any level Element

I have not seen it demonstrated, but after the presentation Billy confirmed that he has seen Vista Gadgets built on WPF. Man, the possibilities here are unbelievable. WPF really is the first GUI paradigm shift we’ve since the GUI was created.

3:10pm update – VS2008 Overview:

  • VS is a shell that hosts other Components
  • Because 3.0 and 3.5 build on 2.0, there is distinct support for each of these three frameworks in VS2008
  • 2008 Solution files are a little different than 2005
  • ASP.NET Web Applicaiton projects have AJAX support built in
  • Intellisense can be hidden by holding the CTRL key down (well, not really hidden, but it becomes translucent)
  • Intellisense is expanded and improved in VS2008: supports LINQ
  • JavaScript Debugging – use F9 to set breakpoints
  • Complete access to the Document object tree in debug
  • There is an ImmediateWindow for making and testing on the fly Script changes
  • WCF support is built in to VS2008
  • WPF Designer is built in to VS2008 (but investigate Blend)
  • WPF anchoring is controlled inside the designer window, not the properties grid
  • ClickOnce support enhaned
  • VS2008 also has XSLT debugging
  • XSLT breakpoints can be set in both theXSLT and the Data Source file
  • Web Apps have a Split Screen designer option
  • Support has been added for nested Master Pages

4:20pm update:

Attended a class on “Expression Blend for Developers” by Billy Hollis. Not really a lot of new information, but it did go into more detail and show some more hands on type use of Blend.

  • Blend is part of the Expression Suite, but Blend is included in MSDN. The rest of the suite is really meant for Graphics Designers.
  • Blend is the preferred tool for developing WPF and SilverLight UI.
  • Blend and Visual Studio share the same projects, so when you create a project in Blend you must select the Framework and Language targets even though you cannot develop code in Blend.
  • Blend is designed for Wide Format screens, so that will grant a better user experience than traditional aspect ratios.
  • Blend will execute code written in VS.
  • Grid is the default root element of any new WPF app in Blend, but it can be changed to other Panel types.
  • Grid Columns are better designed in VS than in Blend: the properties grid in VS makes setting column and row information easier while Blend only allows you to approximate sizes by eye on the design surface.
  • Otherwise, Blend is the superior tool for the UI development.
  • XAML editing in Blend does not have Intellisense (but VS does)
  • Blend has visual tools for creating DataTemplates and Styles and can save them as Resources, either for the Application, Windows, or a ResourceDictionary
  • Blend can set up DataBinding using a drop and drag technique

After all I’ve seen, between WPF and Blend, C# 3.5 and LINQ, all I can say is that I am going to have a lot of fun over the next few months.

Post session update:

The last session of the day was on the new Entity Data Model.? The keynote this morning had already hit most of the highlights, but in this session we actually got to see some of the tools and results.? And again, I am very impressed.? The technology is not ready for prime time (which is fitting since it won’t be released until spring), but it has great promise.? The point of it all is to be able to further abstract the database schema from the objects that use it.? EDM is all about abstraction: data mapping rules stored in XML files are how the complexity is managed.

Basically, the objects are defined as you would actually use them, with no regard to how they relate to database schema.? The framework then generates “go between” code to handle CRUD operations.? LINQ is used heavily to interface with the resulting Entities.? This will definitely be a technology to watch.? Here are some final bullets:

  • Can be done in VS2008, but you need to load the ADO.NET Entity Framework and tools separately
  • Provides graphical modeling of databases and Entities
  • The resulting Entities are then used in lieu of the actual DB connection (using the ADO.NET disconnected model).? In other words, you treat data like objects
  • One Entity can update multiple tables seamlessly, and the schema relationships are maintained
  • If the schema changes, must rerun the wizard to regenerate the new Entities. (unless you are a masochist who likes to do things manually)

More to come tomorrow.? Whew, these days can really wear you out!

Categories: .NET 3.5, C# 3.0, LINQ, WPF
Follow

Get every new post delivered to your Inbox.