Linq to WIQL and Model Generation

In my last post about Linq to WIQL, I created a query on generic fields on the work item object. Fissum work item class can also be extended to access to specific fields of your work item template. This is the job of  model generation tools of the Fissum API. The next version of Fissum comes with two tools: a graphical model selector, and a command line code generation tool. For now, the model selector program does not implement all the functionnalities I want, but for a first version it is quite enough :). The goal of this tool is to generate a xml description of the template. This description is used to generate classes other the work item class by the command line tool:

image 

You also  need to provide a namespace for the generated source code. This tool generates the following xml file:

image

 

The generation tool takes the classes definition in the xml file to generate classes by using the CodeDom API. This is an example of the generated code in C# but the source code can also be generated in VB.Net:

 

  /// <summary>Work Item definition</summary>

  [Fissum.Core.Linq.ModelTypeAttribute("Work Item")]

  [Fissum.Core.Linq.CreatorProviderAttribute(typeof(WorkItemProvider))]

  public partial class WorkItem : Fissum.TeamSystem.WorkItemObject {

 

    internal WorkItem(Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workitem, Fissum.TeamSystem.TeamFoundationServer server) :

        base(workitem, server) {

    }

 

    /// <summary>The person who re-opened the work item</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("Microsoft.VSTS.Common.ActivatedBy")]

    public virtual string ActivatedBy {

      get {

        return this.Field<string>("Microsoft.VSTS.Common.ActivatedBy");

      }

      set {

        this.SetField<string>("Microsoft.VSTS.Common.ActivatedBy", value);

      }

    }

 

    /// <summary>The date and time the work item was re-opened</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("Microsoft.VSTS.Common.ActivatedDate")]

    public virtual System.Nullable<System.DateTime> ActivatedDate {

      get {

        return this.Field<System.Nullable<System.DateTime>>("Microsoft.VSTS.Common.ActivatedDate");

      }

      set {

        this.SetField<System.Nullable<System.DateTime>>("Microsoft.VSTS.Common.ActivatedDate", value);

      }

    }

 

    /// <summary>The person assigned to do the work</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("System.AssignedTo")]

    public virtual string AssignedTo {

      get {

        return this.Field<string>("System.AssignedTo");

      }

      set {

        this.SetField<string>("System.AssignedTo", value);

      }

    }

 

    /// <summary>The person who closed the work item</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("Microsoft.VSTS.Common.ClosedBy")]

    public virtual string ClosedBy {

      get {

        return this.Field<string>("Microsoft.VSTS.Common.ClosedBy");

      }

      set {

        this.SetField<string>("Microsoft.VSTS.Common.ClosedBy", value);

      }

    }

 

    /// <summary>The date and time the work item was closed</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("Microsoft.VSTS.Common.ClosedDate")]

    public virtual System.Nullable<System.DateTime> ClosedDate {

      get {

        return this.Field<System.Nullable<System.DateTime>>("Microsoft.VSTS.Common.ClosedDate");

      }

      set {

        this.SetField<System.Nullable<System.DateTime>>("Microsoft.VSTS.Common.ClosedDate", value);

      }

    }

 

    /// <summary>The priority of the work item</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("CodeStudio.Rank")]

    public virtual string CodeStudioRank {

      get {

        return this.Field<string>("CodeStudio.Rank");

      }

      set {

        this.SetField<string>("CodeStudio.Rank", value);

      }

    }

 

    /// <summary>The description of how the work item was closed</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("CodePlex.ClosedComment")]

    public virtual string CodePlexClosedComment {

      get {

        return this.Field<string>("CodePlex.ClosedComment");

      }

      set {

        this.SetField<string>("CodePlex.ClosedComment", value);

      }

    }

 

    /// <summary>The person who re-opened the work item</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("CodePlex.ReOpenedBy")]

    public virtual string CodePlexReOpenedBy {

      get {

        return this.Field<string>("CodePlex.ReOpenedBy");

      }

      set {

        this.SetField<string>("CodePlex.ReOpenedBy", value);

      }

    }

 

    /// <summary>The person who reported the work item</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("CodePlex.ReportedBy")]

    public virtual string CodePlexReportedBy {

      get {

        return this.Field<string>("CodePlex.ReportedBy");

      }

      set {

        this.SetField<string>("CodePlex.ReportedBy", value);

      }

    }

 

    /// <summary>The person who last updated the work item</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("CodePlex.UpdatedBy")]

    public virtual string CodePlexUpdatedBy {

      get {

        return this.Field<string>("CodePlex.UpdatedBy");

      }

      set {

        this.SetField<string>("CodePlex.UpdatedBy", value);

      }

    }

 

    /// <summary>The number of votes from users</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("CodePlex.UserVotes")]

    public virtual System.Nullable<int> CodePlexUserVotes {

      get {

        return this.Field<System.Nullable<int>>("CodePlex.UserVotes");

      }

      set {

        this.SetField<System.Nullable<int>>("CodePlex.UserVotes", value);

      }

    }

 

    /// <summary>The reason why the work item has the current status</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("System.Reason")]

    public virtual string Reason {

      get {

        return this.Field<string>("System.Reason");

      }

      set {

        this.SetField<string>("System.Reason", value);

      }

    }

 

    /// <summary>The status of the work item</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("System.State")]

    public virtual string State {

      get {

        return this.Field<string>("System.State");

      }

      set {

        this.SetField<string>("System.State", value);

      }

    }

 

    /// <summary>The date and time of the last change to the status</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("Microsoft.VSTS.Common.StateChangeDate")]

    public virtual System.Nullable<System.DateTime> StateChangeDate {

      get {

        return this.Field<System.Nullable<System.DateTime>>("Microsoft.VSTS.Common.StateChangeDate");

      }

      set {

        this.SetField<System.Nullable<System.DateTime>>("Microsoft.VSTS.Common.StateChangeDate", value);

      }

    }

 

    [Fissum.TeamSystem.Model.FieldAttribute("System.WorkItemType")]

    public virtual string WorkItemType {

      get {

        return this.Field<string>("System.WorkItemType");

      }

    }

 

    /// <summary>The type of work item</summary>

    [Fissum.TeamSystem.Model.FieldAttribute("CodeStudio.WorkItemType")]

    public virtual string CodePlexWorkItemType {

      get {

        return this.Field<string>("CodeStudio.WorkItemType");

      }

      set {

        this.SetField<string>("CodeStudio.WorkItemType", value);

      }

    }

  }

 

The "<summary></summary>" help string containes the same description as the description written is the work item template, so you can use it while you're using your model:

image

 

As the generated class inherits from my work item base class, I can use it in the LINQ query:

 

var q = (from wi in project.Get<Fissum.Model.Codeplex.WorkItem>()

        where wi.CodePlexWorkItemType == "Feature"

        orderby wi.CodePlexUserVotes descending

        select wi

        ).ToList();

 

This is the generated WIQL query:

SELECT [System.Id]
FROM WORKITEMS
WHERE (([CodeStudio.WorkItemType] = @P0)) AND (System.TeamProject = @project) AND (System.WorkItemType = 'Work Item')
ORDER BY [CodePlex.UserVotes] desc

Where all the "where" tests come from? This is simple:

  • The first test comes from the query itself
  • The test on the project is here because the query is query on a projet. You cannot use specialized work item classes directly on a server because each project can have a specific template.
  • The test "System.WorkItemType = 'Work Item'" is generated from the attribute ModelTypeAttribute of the WorkItem class

 

In this version, there is no integrity test between the model and the project because it is not as simple as comparing the project template definition with the template used to generate the class source. But I'm working on it :)

Print | posted on Monday, May 05, 2008 12:12 PM

Comments have been closed on this topic.