in
Forums
Blogs
Files
Devexpress.Com
ClientCenter
Support Center
DevExpress Channel

Gary's Blog

August 2008 - Posts

  • XAF Cookbook #1 – Quickly Create a Contact Management Application

    Problem

    You need to quickly create an application to manage Contacts. You want both win form and web form applications.

    Solution

    Use XAF to create the win form and web form solutions and sub class the built in Person class to create the Contact class.

    Discussion

    By default XAF creates both a win form and web form application out of the box. Create a new XAF application and give it a suitable name. Since a Contact is a “kind of” Person, subclass the built in Person class to create your required Contact class, adding any extra properties you require.

    using System;
    using DevExpress.Xpo;
    using DevExpress.ExpressApp;
    using DevExpress.Persistent.Base;
    using DevExpress.Persistent.BaseImpl;
    using DevExpress.Persistent.Validation;
    
    namespace XAFCookbook_001.Module {
        [DefaultClassOptions]
        public class Contact : Person {
            public Contact(Session session) : base(session) { }
    
            private string _SpouseName;
            public string SpouseName {
                get {
                    return _SpouseName;
                }
                set {
                    SetPropertyValue("SpouseName", ref _SpouseName, value);
                }
            }
        }
    }

    In this example I have added the extra property SpouseName to the Contact class (using the CR template “XPS”), you should add any extra properties required in the same way.

    By default, the win form project is the startup project. Press F5 to launch the win form application. Note your Contact class has inherited the properties, and the view layout, from the Person class. Note also the addition of your SpouseName property.

    Switch the startup project to be the web form project and launch the application once more. Note you have the same layout and functionality as you did in the win form application.

    Technorati tags:
    Digg This
  • .NET Framework 3.5 SP1 Sources are available!

    During the past weeks we have been working on preparing the source code for the .NET Framework 3.5 SP1 release and we are happy to announce that we just released the following components to the Reference Source Code Center (RSCC) servers:

    Reference Source Code Center Team Blog

    Digg This
  • XPO Cookbook #5 – Creating Persistent Objects for an Existing Database

    Problem

    You have an existing database for which you have to create an application and so wish to create a set of persistent objects to reflect the table(s) you have to work with.

    Solution

    Use the PersistantClasses Wizard to generate the classes for you, then use as normal.

    using System;
    using DevExpress.Xpo;
    using AdventureWorks;
    using DevExpress.Data.Filtering;
    
    class Program {
        static void Main(string[] args) {
            //GS - Create and save a contact
            using (UnitOfWork uow = new UnitOfWork()) {
                new Person_Contact(uow) {
                    FirstName = "Gary",
                    LastName = "Short"
                }.Save();
                uow.CommitChanges();
            }
    
            //GS - Read the contact back to prove it is persisted
            using (UnitOfWork uow = new UnitOfWork()) {
                Person_Contact contact = 
                    uow.FindObject<Person_Contact>(
                        new BinaryOperator("FirstName", "Gary"));
    
                if (contact != null) {
                    Console.WriteLine(String.Format(
                        "Contact first name {0} has been written to the database",
                            contact.FirstName));
                };
            }
    
            //GS - Reset database
            using (UnitOfWork uow = new UnitOfWork()) {
                Person_Contact contact = 
                    uow.FindObject<Person_Contact>(
                        new BinaryOperator("FirstName", "Gary"));
    
                if (contact != null) {
                    uow.Delete(contact);
                    uow.CommitChanges();
                }
            }
        }    
    }

    Discussion

    The PersistentClasses Wizard will allow you to select the table(s) and field(s) you wish to select from your existing database; it will then generate persistent class(es), for the selected items, in a single class, thus not polluting your project if you have generated dozens of classes. In the example above I generated the Person.Contact table from the AdventureWorks sample database.

    From here, you can either use the classes as normal (as per the example above) or you can subclass one or more of these generated classes and place your business logic and any non persistent properties in these subclasses.

    Technorati tags:
    Digg This
  • XPO Cookbook #4 – Persisting an Existing Hierarchy by Implementing Interfaces

    Problem

    You want to use XPO as an ORM tool. You have an existing hierarchy of business objects that you wish to persist, but you want a more flexible solution than that provided by using attributes.

    Solution

    Assume we have the very simplistic business object below:-

    public class Car {
    
        private string _Make;
        public string Make {
            get { return _Make; }
            set {
                _Make = value;
            }
        }
    
        private string _Model;
        public string Model {
            get { return _Model; }
            set {
                _Model = value;
            }
        }
        
        public Car() {
            
        }
    }

    After the required modifications, and the addition of some code to test it, the example now looks like this:-

    using System;
    using DevExpress.Xpo;
    using DevExpress.Xpo.Metadata;
    using System.Collections;
    using DevExpress.Data.Filtering;
    
    
    class Program {
        static void Main(string[] args) {
            //GS - Test our hierarchy is now persistent
    
            //GS - Create and save a Car
            using (UnitOfWork uow = new UnitOfWork()) {
                Car car = new Car(uow) {
                    Make = "Ford",
                    Model = "Fiesta"
                };
                car.Save();
                uow.CommitChanges();
            }
    
            //GS - Read back the car
            using (UnitOfWork uow = new UnitOfWork()) {
                Car car = FindCarByMake("Ford", uow);
                Console.WriteLine(String.Format(
                    "Make = {0}, Model = {1}", 
                    car.Make, 
                    car.Model));
            }
    
            //GS - Delete the Car
            using (UnitOfWork uow = new UnitOfWork()) {
                Car car = FindCarByMake("Ford",uow);
                car.Delete();
                uow.CommitChanges();
            }
    
            //GS - Prove the car has been deleted
            using (UnitOfWork uow = new UnitOfWork())
            {
                Car car = FindCarByMake("Ford",uow);
                if(car == null){
                    Console.WriteLine("Car has been deleted!");
                }
    
                else{
                    Console.WriteLine("Something went wrong!");
                }
            }
        }
    
        private static Car FindCarByMake(string make, UnitOfWork uow) {
            BinaryOperator bo = new BinaryOperator("Make", make);
            return uow.FindObject<Car>(bo);
        }
    }
    
    //GS - Create an existing hierarchy
    public class Car : IXPObject, IComparable {
    
        private string _Make;
        public string Make {
            get { return _Make; }
            set {
                _Make = value;
                OnChanged("Make");
            }
        }
    
        private string _Model;
        public string Model {
            get { return _Model; }
            set {
                _Model = value;
                OnChanged("Model");
            }
        }
        
        public Car() {
            
        }
    
        //GS - Provide an Id for our object
        private int _Id;
        [Key(true)]
        public int Id {
            get { return _Id; }
            set {
                _Id = value;
                OnChanged("Id");
            }
        } 
    
        //GS - Provide a backing store for Session and ClassInfo
        private Session _Session;
        private XPClassInfo _ClassInfo;
    
        //GS - Provide a constructor for our object that takes a Session object
        public Car(Session session) {
            _Session = session;
            _ClassInfo = session.Dictionary.GetClassInfo(this.GetType());
            if (!IsLoading)
                AfterConstruction();
        }       
    
        //GS - Write any post construction code here
        private void AfterConstruction() { }
    
        //GS - Create a backing store and a property for the IsLoading bool
        bool _IsLoading;
        [NonPersistent]
        public bool IsLoading { get { return _IsLoading; } }
        
        //GS - Define the Changed event
        public event ObjectChangeEventHandler Changed;
    
        //GS - Raise the Change event
        protected void RaiseChangeEvent(ObjectChangeEventArgs args) {
            if (Changed != null)
                Changed(this, args);
        }
    
        public void OnChanged() {
            if (!IsLoading)
                RaiseChangeEvent(new ObjectChangeEventArgs(ObjectChangeReason.Reset));
        }
    
        protected void OnChanged(string propertyName) {
            if (!IsLoading)
                RaiseChangeEvent(
                    new ObjectChangeEventArgs(ObjectChangeReason.PropertyChanged,
                        propertyName));
        }
    
        //GS - Provide general persistence methods
        public void Save() {
            Session.Save(this);
        }
    
        public void Delete() {
            Session.Delete(this);
            RaiseChangeEvent(new ObjectChangeEventArgs(ObjectChangeReason.Delete));
    
        }
    
        public void Reload() {
            Session.Reload(this);
            RaiseChangeEvent(new ObjectChangeEventArgs(ObjectChangeReason.Reset));
        }    
    
        #region IXPObject Members
    
        public void OnDeleted() {}
    
        public void OnDeleting() {}
    
        public void OnLoaded() {
            _IsLoading = false;
        }
    
        public void OnLoading() {
            _IsLoading = true;
        }
    
        public void OnSaved() {}
    
        public void OnSaving() {}
    
        #endregion
    
        #region IXPClassInfoProvider Members
    
        public XPClassInfo ClassInfo {
            get { return _ClassInfo; }
        }
    
        #endregion
    
        #region IXPDictionaryProvider Members
    
        public XPDictionary Dictionary { get { return Session.Dictionary; } }
    
        #endregion
    
        #region ISessionProvider Members
    
        public Session Session {
            get { return _Session; }
        }
    
        #endregion
    
        #region IDataLayerProvider Members
    
        public IDataLayer DataLayer {get {return Session.DataLayer;}}
    
        #endregion
    
        #region IComparable Members
    
        public int CompareTo(object obj) {
            return Comparer.Default.Compare(Session.GetKeyValue(this),
              Session.GetKeyValue(obj as IXPSimpleObject));
        }
    
        #endregion
    }

    Discussion

    To make an existing hierarchy persistent, using interfaces, the first thing we do is to modify the the class definition so that it implements the IXPObject and IComparable interfaces. Then we add a property to hold the Id of the object (note the use of the key attribute to specify that the key should be auto generated), and implement change notification in that property and the other properties already defined in our class.

    Following that we create a backing store for the Session and ClassInfo objects and implement a constructor, for our class, that sets those fields. We also, at this point, provide a hook for developers to place any intialisation code that must be run post construction.

    The next thing we do is to code the change notification that we called from our properties when we made those changes above, before coding the general persistence methods of Save(), Reload() and Delete().

    This completes the work we have to do on our own class, and all that remains for us to do is to implement the methods required by the interfaces.

    Technorati tags:
    Digg This
  • XPO Cookbook #3 – Persist an Existing Hierarchy Using Attributes

    Problem

    You wish to use XPO as an ORM tool. You have an existing hierarchy of business objects and you do not wish to implement any extra interfaces.

    Solution

    Assume you have the following hierarchy of business objects where Employee inherits from Person:-

    //GS - Create an existing hierarchy
    public class Person { private string _Name; public string Name { get { return _Name; } set { _Name = value; } } private DateTime _DateOfBirth; public DateTime DateOfBirth { get { return _DateOfBirth; } set { _DateOfBirth = value; } } public Person() { } } public class Employee : Person { private string _EmployeeNumber; public string EmployeeNumber { get { return _EmployeeNumber; } set { _EmployeeNumber = value; } } public Employee() { } }

    After adding support for XPO the hierarchy will look like this:-

    [Persistent]
    public class Person {
    
        private int _Id;
        [Key(true)]
        public int Id {
            get { return _Id; }
            set {
                _Id = value;
            }
        }
        
        private string _Name;
        public string Name {
            get { return _Name; }
            set {
                _Name = value;
            }
        }
    
        private DateTime _DateOfBirth;
        public DateTime DateOfBirth {
            get { return _DateOfBirth; }
            set {
                _DateOfBirth = value;
            }
        }
        
        public Person() {
            
        }
    }
    
    [Persistent]
    public class Employee : Person {
    
        private string _EmployeeNumber;
        public string EmployeeNumber {
            get { return _EmployeeNumber; }
            set {
                _EmployeeNumber = value;
            }
        }
        
        public Employee() {
            
        }
    }

    Creating, modifying and saving objects from this hierarchy are now done in the same way as if the objects inherited from one of the XPO classes in the first place. The full example now looks like this:-

    using System;
    using DevExpress.Xpo;
    
    
    class Program {
        static void Main(string[] args) {
            XpoDefault.Session.Save(new Employee() { 
                Name="Gary",
                DateOfBirth = DateTime.Parse("24/01/1970"),
                EmployeeNumber = "RA 1234"
            });
        }
    }
    
    [Persistent]
    public class Person {
    
        private int _Id;
        [Key(true)]
        public int Id {
            get { return _Id; }
            set {
                _Id = value;
            }
        }
        
        private string _Name;
        public string Name {
            get { return _Name; }
            set {
                _Name = value;
            }
        }
    
        private DateTime _DateOfBirth;
        public DateTime DateOfBirth {
            get { return _DateOfBirth; }
            set {
                _DateOfBirth = value;
            }
        }
        
        public Person() {
            
        }
    }
    
    [Persistent]
    public class Employee : Person {
    
        private string _EmployeeNumber;
        public string EmployeeNumber {
            get { return _EmployeeNumber; }
            set {
                _EmployeeNumber = value;
            }
        }
        
        public Employee() {
            
        }
    }

    Discussion

    To enable the initial object hierarchy to be persisted by XPO the following steps were carried out:-

    1. The Persistent attribute was added to both the Person and the Employee Classes.
    2. A new property (Id) was added to Person (this is inherited by Employee).
    3. The Key attribute was added to the Id property and a boolean parameter of true was passed to it to indicate that the key should be generated automatically.
    Technorati tags:
    Digg This
  • XPO Cookbook #2 – Change the Default Database

    Problem

    You want to persist your objects to a MS SQL Server database instead of the default access database

    Solution

    using System;
    using DevExpress.Xpo;
    using DevExpress.Xpo.DB;
    
    class Program {
        static void Main(string[] args) {
            string conn =
                MSSqlConnectionProvider.GetConnectionString(".",
                    "XPOCookbook");
    
            XpoDefault.DataLayer =
                XpoDefault.GetDataLayer(conn,
                    AutoCreateOption.DatabaseAndSchema);
        }
    }

    Discussion

    To connect to a SQL Server database, instead of the default Access database, the first thing that we have to do is to create the required connection string by calling the GetConnectionString() method on the MSSqlConnectionProvider class and passing in the server name and database name. Having thus obtained the connection string, we can then make our database the default one used by XPO by setting the XpoDefault DataLayer property to the result of calling the GetDataLayer() method, on the XpoDefault class, passing in the connection string and setting the AutoCreateOption.

    Technorati tags:
    Digg This
  • XPO Cookbook #1 – Quickly Serialise an Object

    Problem

    You want to serialise an object as quickly as possible and you have no preference as to which RDBMS is used.

    Solution

    using System;
    using DevExpress.Xpo;
    
    class Program {
        static void Main(string[] args) {
            //GS - Create a unit of work to work within
            using (UnitOfWork uow = new UnitOfWork())
            {
                //GS - Create and serialize a person
                Person person = new Person(uow) { 
                    FistName = "Gary", 
                    LastName = "Short", 
                    DateOfBirth = DateTime.Parse("24/01/1970") 
                };
    
                uow.CommitChanges();
            }
        }
    }
    
    //GS - Define a Person Class
    public class Person : XPObject {
        public Person(Session session)
            : base(session) { }
    
        private string _FistName;
        public string FistName {
            get {
                return _FistName;
            }
            set {
                SetPropertyValue("FistName", ref _FistName, value);
            }
        }
        private string _LastName;
        public string LastName {
            get {
                return _LastName;
            }
            set {
                SetPropertyValue("LastName", ref _LastName, value);
            }
        }
        private DateTime _DateOfBirth;
        public DateTime DateOfBirth {
            get {
                return _DateOfBirth;
            }
            set {
                SetPropertyValue("DateOfBirth", ref _DateOfBirth, value);
            }
        }
    }

    Discussion

    The first thing to notice is that I have more than one class defined in my source file. Such things are normally frowned upon in favour of a “one class, one file” mantra, and rightly so. However, I am not writing an application for production here, I’m writing code for a blog post and it makes it easier to discuss if all the code is displayed; it also makes it easier for you to cut, paste and run the example if you so wish. I will be defining all my classes in the one source file for all of the recipes in this cookbook, but I will only be explaining the rationale once. If you wish, you may take bets on how far into the cookbook I get before someone comments along the lines of “shouldn’t you have one file per class?”. When they do, the reader who guessed closest to the recipe number wins; when it happens you can also point the commenter here for an explanation. :-)

    Anyway, on to the explanation of the recipe. Firstly let’s chat about the business object we have created for serialisation. The first thing to notice is that our class inherits from XPObject, one of three classes that your business objects can inherit from when using XPO, more on the other two in future recipes. XPObject gives us support for unique keys and optimistic locking out of the box and is the class inherited from if you use the CodeRush template to create your business object. The CodeRush template is the recommended way to create such business classes and is the route I always take. The mnemonic for this template is “xc”.

    The next thing to notice about our business object is the setter for the properties uses the SetPropertyValue method, this allows XPO to handle change management for you and is one less thing for you to worry about. The CodeRush templates for adding these properites (“xps” for string properties and “xpd8” for the DateTime property) adds the call to SetPropertyValue for you and is, again, the recommended route.

    To make use of our business object we create a UnitOfWork. The UnitOfWork inherits from Session and the benefit it gives us developers is that we no longer have to keep track of all the changes to our persistent classes ourselves. When we used the Session object each instance of our business objects had to be sent the Save() message in order to be persisted. When using UnitOfWork this is no longer the case, the UnitOfWork tracks all the changes for you and they are persisted by making one call to CommitChanges() once you have made all the required changes to all of your objects and you are ready to serialise your object graph.

    The last thing to mention is that the default persistence mechanism is to serialise the object graph to an Access database. We shall examine how to change this default behaviour in a future recipe.

    Technorati tags: ,
    Digg This
  • Cooking up a Storm with XPO and XAF

    My wife likes to cook – which is good for me, as I like to eat – and every time I watch her in the kitchen I can’t help but notice the parallels between chefs and programmers.

    There are chefs who work for large hotels and conference centres who prepare large banquets for guests and attendees, as well as numerous lunches and snacks throughout the day. This is analogous to the enterprise programmer who works on enterprise scale systems such as accounting and CRM, but who also finds himself having to patch together a myriad of scripts to fulfill the extraneous requirements of of those further up the enterprise food chain. There are also chefs who work in smaller hotels and cafes, providing meals on a, some what, ad hoc basis to passing customers, these chefs are analogous to the smaller coding shops who tend to work on a customer by customer basis. Each, in their own way, striving to find the best ingredients to put together to make a superb dish to delight their customers.

    When it comes to ingredients I am fortunate enough to live in an area that constitutes some of the best agricultural land in Scotland; in fact the Carse of Gowrie is famed the world over for the quality of it’s soft fruit (that’s raspberries and the like to you and me). It’s the same when we speak of “ingredients” for applications too, I’m lucky enough to work for a company who provide programmers with some of the best “ingredients” available.

    Another parallel I see between chefs and programmers is in books. My wife loves cookbooks, almost as much as I love technical books. Chefs have books that explain everything it takes to run a kitchen, as we have books that explain enterprise architecture. Chefs have speciality books that concentrate on one small facet of cooking and we have similar books in our world. So it is with this in mind that I decided to start two little “books” of my own; the XAF Cookbook and the XPO Cookbook, look out for them in future posts. I hope you enjoy them and that they help you cook up some “tasty dishes” of your own.

    Digg This
  • XPOlympics – Serialising RSS Feeds Using XPO

    Although the UK is a crowded island sitting on the border of the Atlantic Ocean and the North Sea, comfortably far from mainland Europe, its population is relatively small; in fact when compared to the those of China or India it is, in fact, tiny (estimated to be 60.7 million as of July 2007). Perhaps it is this fact that means I am always surprised when the UK does well at global scale sporting events such as the Olympics, and there is no doubt that Team GB (more correctly Great Britain and Northern Ireland) has excelled at these games, putting in the best performance, in terms of medal haul, since the 1908 games.

    So what has all this to do with XPO? Well I like to keep up with what is going on at the Olympics but that “work thing” just keeps getting in the way. Coupled with that I’d really like to record all the news so that I can go back and analyse  it after the event. So, what I really need is a little application to handle the following requirements:

    1. Read an XML file and fetch one or more RSS feed URLs
    2. For each feed
      1. Check if that feed has been serialised previously
        1. If it hasn’t
          1. Create it
        2. If it has then fetch the matching feed object from the database
      2. Send a HEAD request to the web server for the RSS feed file header information
        1. Examine the last-modified header
          1. If there is no last-modified header then skip this file
          2. If the file has not been updated since last read then skip the file
      3. Fetch all the news items from the RSS feed
        1. For each news item
          1. Create a news item object
          2. Check if the fetched / created feed object has this news item already
            1. If it does then skip this news item
            2. Otherwise add the news item to the feed
      4. Set the lastUpdate date to now.
    3. Serialise the newly created object graph to the database
    4. This process must be able to be automated using the Windows AT command

    Looking at the requirements, it’s clear to see that, apart from doing a few sensible checks, all that is required is that an RSS feed is serialised to a database, that sounds to me like a perfect job for XPO. Now, a blog posting is not a suitable place to examine such an application line by line (I leave that as an exercise for the reader) but let’s look at some of the more pertinent points of the application.

    Firstly I could have used an OPML file to contain my list of RSS feed URLs that is, after all, what it was designed for. However, I felt that was a little overkill for the purposes of our application and so I went with a more simplified “roll you own” file structure as shown below.

    <?xml version="1.0" encoding="utf-8" ?>
    <Feeds>
      <Feed>
        <Name>Feed Name</Name>
        <Url>Feed URL</Url>
      </Feed>  
    </Feeds>

    Having specified which feeds we wish to read (my application reads the 32 BBC feeds dedicated to the Olympics) we should now go ahead and specify our Feed and NewsItem domain objects. I’m not going to cover that here as it is clearly documented on our web site.

    The first thing I’d like to draw your attention to is the fact that, by default, XPO will serialise objects to an Access database, if you want to use another database (and we support over 15 RDBMSs) then you have to inform XPO like so:

    private void SetUpXPODataLayer() {
        string conn =
            MSSqlConnectionProvider.GetConnectionString(".",
                "XPOlympics");
    
        XpoDefault.DataLayer =
            XpoDefault.GetDataLayer(conn,
                AutoCreateOption.DatabaseAndSchema);
    }

    The next thing I want to draw your attention to is not specifically XPO related but is, never the less, interesting. It is the technique of only fetching the header information from the web server to ascertain whether or not a file has been updated, this prevents you having to download the entire file unnecessarily and is done like this:

    //GS - Make a request for the feed header info only and 
    //get the last-modified date
    HttpWebRequest webRequest =
        HttpWebRequest.Create(feed.Url) as HttpWebRequest;
    webRequest.Method = "HEAD";
    webRequest.KeepAlive = false;
    
    WebResponse webResponse = null;
    string lastModifiedDateString = String.Empty;
    try {
        webResponse = webRequest.GetResponse();
        lastModifiedDateString =
        webResponse.Headers.Get("Last-Modified");
    }
    catch (WebException wex) {
        Trace.WriteLine(String.Format("{0} - {1} {2}",
            DateTime.Now, wex.Message, feed.Name));
        Trace.Flush();
        Trace.Close();
        continue;
    }
    finally {
        if (webResponse != null) {
            webResponse.Close();
        }
    }

    Note the use of the “KeepAlive = false;” line above, this prevents the HttpWebRequest object from keeping the connection open and causing “connection leaks”.

    Whilst I’m on the subject of things which are not specifically XPO related but are interesting anyway, note the use of LINQ to XML to extract the news items from the feed, isn’t that syntax so much nicer that the XPath way of doing things?

    var newsItems =
        from item in feedDoc.Descendants("item")
        select new {
            Title = item.Element("title").Value,
            Description = item.Element("description").Value,
            PubDate = item.Element("pubDate").Value,
            Category = item.Element("category").Value,
            Url = item.Element("link").Value
        };

    Anyway, this is an XPO blog so let’s get back on topic shall we? Having fetched or created a new feed and extracted the news items from the RSS document we want to add the news item to the feed, but only if it hasn’t been added before, we don’t want duplicate news items in our feed. We can use XPO to check it’s not been added already this way:

    if (!aFeed.NewsItems.Contains<NewsItem>(aNewsItem)) {
        aFeed.NewsItems.Add(aNewsItem);
    }

    Now, all that remains for us to do is to serialise our newly created object graph to the database by calling CommitChanges() on the UnitOfWork object.

    If you would like to download the full application and have a look at it, you can get it here.

    Technorati tags: , ,
    Digg This
  • The eXpressApp Application Framework, Project Mojave and Show-stoppers

    The provenance of the word show-stopper dates back to the music hall days when a performer’s act was so good that the show was quite literally brought to a stop by the audience’s applause. Of course, time moves on and the word has taken on an altogether more sinister meaning, with it now conjuring up the idea of a fault so catastrophic as to bring the use of something, or the sale of something, to a premature end. A good example of this is the Millennium Bridge, the most recent bridge to be built across the Thames in London.

    The Millennium Bridge is a foot bridge crossing the Thames at St. Paul’s. It opened on June 10 2000. Now every structure has a resonance frequency, a frequency at which it will oscillate at maximum amplitude. Unfortunately for the Millennium Bridge, it’s resonance frequency was close to the natural footfall of the average person, not good on a foot bridge! The result was that when people walked on it, it swayed, as it swayed people naturally fell instep with the swaying motion, which amplified the swaying motion and so and and so forth in a feedback loop. Before long the bridge was swaying wildly and it was finally closed to the public on June 12 2000 to enable remedial engineering work to be carried out. A true show-stopper in the modern sense of the word.

    Of course we are more familiar with the term show-stopper to mean a fault, or a series of faults, that render a software product unusable. The most stark example of this at the moment is probably Microsoft’s Vista operating system. When Vista shipped it received some bad press and in this age of the blogsphere echo chamber that negative press was passed on and amplified, to the point now where users who have never seen, let alone installed, Vista think it is a terrible product and will quite happily tell anyone who will listen all about it’s failings and short comings. This negative impression of Vista could become, not so much a show-stopper, but something which could seriously retard the sales of Vista.

    It’s hard to get out from underneath the snowball of such negativity, fueled as it is by the echoing nature of the blogsphere, but Microsoft have attempted to do just that with Project Mojave. In this experiment a number of people, who had a pre-existing negative view of Vista, were shown a “new” operating system called Mojave. They all thought the new operating system was amazing and wanted to know when they could upgrade to it; only then were they told that they had, in fact, just been shown Vista. Whether initiatives like this are enough to combat the negativity surrounding Vista remain to be seen, but it is certainly a good start.

    To a certain extent we suffer a similar problem with XAF, not around the quality of the product, everyone I show it to loves it, but there is a perception that XAF has a steep learning curve, and that learning curve is putting people off taking up the framework. Well guess what, those people are not wrong, they are just not completely right. Now XAF has a learning curve, there is no doubt about that, however it is worth noting that every framework, which increases developer productivity, is going to have a learning curve and the more a framework does for you, the more productive you are, the more there is going to be to learn.

    So, now that we have established that there is no getting away from the learning curves associate with an application framework, what are DevExpress doing to help? Well we are tackling the problem on a number of fronts. Firstly, there is the documentation, then there are the videos and lastly, but I hope not least, there are evangelists like me. If you have an issue regarding not being able to work out how the framework works in a particular area, then please feel free to get in touch with me at garysATdevexpressDOTcom. Trust me, the view from the top is worth the effort. :-)

    Technorati tags: ,
    Digg This
  • XPO Will Benefit from the Entity Framework

    Yesterday, as I was pondering the internals of the XAF model for my ongoing localization project, I received an email from the Microsoft Community Leaders mailing list informing me that the Entity Framework will ship as part of Visual Studio 2008 SP1 later this year. Now - as you ponder which is the more disturbing part of that sentence, the fact that I’m a community leader in Scotland or the fact that the Entity Framework is soon to be released into the wild – let me tell you that, around the same time as I received that email, I was listening to a podcast where a group of well known developers were discussing the Entity Framework.

    Whilst discussing it’s short comings, those developers were traveling a well worn path. Those of us with an interest in the ORM tool space (and hopefully that is everyone reading this blog) are well aware of the areas in which this first release version of the Entity Framework will fall short, namely:  focusing on the data aspects of the entity at the expense of the behavioral aspects; the excess code developers will have to write in order to cope with the poor decisions taken by the team around the lazy loading of associated entities; the Entity Framework’s view of a shared model which flies in the face of best practice and other such failings that we need not dredge up here.

    However, the most interesting point made in the podcast and the one I am echoing here in this blog post, was that the release of the Entity Framework this summer is to be broadly welcomed amongst vendors and consumers of ORM tools. Why is that you ask, when the framework falls so obviously short of the required mark? Well it is a sad fact of life that many companies and many individual developers too for that matter, will not contemplate looking at a new architectural paradigm until such time as it appears on the Microsoft development stack. Whist there are those of us who are happy to inhabit the world of XPO, NHibernate and other ORM tools, it remains a sad fact that we, ladies and gentlemen, are very much in the minority.

    With the release of Visual Studio 2008 SP1 this summer, that is all about to change, an ORM tool (albeit a flawed one) will then become a first class citizen in the Microsoft development stack. That fact will open up the world of ORM to many more people, and as those people explore that new world many will drift to XPO and other ORM tools, making 2009, in my opinion, a great year to be in the ORM space. We think XPO is a great ORM tool and we look forward to welcoming all the new users that the Entity Framework will introduce us to.

    Digg This
Copyright © 1998-2008 Developer Express Inc.
ALL RIGHTS RESERVED