Bryan Reynolds

Software, Business, Life . . .

Contact

Bryan Reynolds
  Bryan Reynolds Linked In
E-mail me Send mail

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010

NDepend and complex methods.

First I want to say I am no expert on NDepend. I have just begun my journey. If you are unfamiliar with NDepend here is a description straight from there website.

"NDepend is a tool that simplifies managing a complex .NET code base. Architects and developers can analyze code structure, specify design rules, plan massive refactoring, do effective code reviews and master evolution by comparing different versions of the code. "

This is no lie!  For those of you who are starting to analyze your code and are attempting to improve the overall architecture this product is a must have.

 

Getting Started

To get started its pretty straight forward.  You take your compiled assembly's and point NDepend at them.  Here are instructions straight from the quick start tutorial. 

After unzipping the software into a directory of your choosing, there is no installation program, you follow these steps.

  1. Run VisualNDepend.exe.  There is no shortcut you will need to load it from where you unzipped it.
  2. Select the option: Select assemblies to analyze.
  3. Populate the data grid with your assemblies by using the browse button or by using drag&drop.
  4. Click OK. (This will take a few minutes)

 

The result will look something like this.

image

 

Here are a list of some short beginning video tutorials to get you started.  I have to admit a prefer short videos and NDepend does not disappoint.  Everyone's time is extremely valuable and getting to the heart of the matter, matters!

NDepend Basics

Analyzing Assemblies

Building a NDepend Project

 

Complex Methods

It would take 1000 blog posts to go through how you can use this product.  Today I just wanted to show you how I used it to identify a function that was more complex than it needed to be.

Below is a code snippet of a method of a class that manages Excel files.  It is designed to take a regular expression and search all sheets and all cells for a match.  Once the match is found the method return the associated cell.

 

   1: public Cell GetCellByRegEx(string regularExpression)
   2:       {
   3:           Check.Require(this._xlsFile != null);
   4:           Check.Require(!string.IsNullOrEmpty(regularExpression));
   5:  
   6:           var colCount = this._xlsFile.ColCount;
   7:           var rowCount = this._xlsFile.RowCount;
   8:           var sheetcount = this._xlsFile.SheetCount;
   9:  
  10:           for (var s = 1; s < sheetcount; s++)
  11:           {
  12:               this._xlsFile.ActiveSheet = s;
  13:  
  14:               for (var r = 1; r <= rowCount; r++)
  15:               {
  16:                   for (var c = 1; c <= colCount; c++)
  17:                   {
  18:                       var v = this._xlsFile.GetCellValue(r, c);
  19:                       if (v != null)
  20:                       {
  21:                           var regex = new Regex(
  22:                               regularExpression,
  23:                               RegexOptions.IgnoreCase);
  24:                           var matches = regex.Matches(v.ToString());
  25:  
  26:                           if (matches.Count > 0)
  27:                           {
  28:                               var cell = new Cell { Row = r, Column = c, Value = v.ToString() };
  29:  
  30:                               return cell;
  31:                           }
  32:                       }
  33:                   }
  34:               }
  35:           }
  36:  
  37:           return null;
  38:       }
There is a section for code quality query's within NDepend.  It is designed to run through your code and analyze how it is constructed based on query's made by the developers of the product.  These rules of course are based on what they believe is a best practice.  Users of the product will end using there own skill to determine what is right or wrong.  The goods news is that you can change these CQL queries at any time.  Below is a screen capture of what a CQL looks like. 
I have highlighted below a CQL result that describes "Methods too complex".  There are 4 methods in my project that have been deemed too complex.
image
The above method "GetCellByRegEx" has a IL Nesting depth of 5.  When you select a query result below you will see a listing of the methods that make up that result. 
image
On the bottom right hand side of the NDepend screen shows the results of the CQL Code Quality queries run against your code assembly.
image
Shows when you select edit on the "Methods too complex" CQL item.

Solving the Problem

Now that you have identified that you have a method that is too complex what do you do.  Just fix it right!  Easier said than done is most cases.  There is some good news though. Most of the CQL items I have seen provide you with some assistance right in the query edit screen.  Looking closely CQL Query Edit screen you will see a link to help on this subject.

Here is a snippet from NDepend that covers what this query is suppose to track and what they recommend.

IL Nesting Depth: The metric Nesting Depth for a method is the maximum number of encapsulated scopes inside the body of the method. The metric IL Nesting Depth is computed from the IL code. Values computed are very similar to what we would expect by computing them from the C# or VB.NET source code.
When you have a testing condition with N conditions, such as if( i > 9 && i < 12) then it is considered as N scopes because it is possible to decompose such conditions into N atomic conditions.
When a method has a large number of case statements corresponding to a switch, the C# and VB.NET compiler generally produce optimizations while generating the IL. In such case, the IL Nesting Depth corresponding value might be slightly higher to what you would expect.


Recommendations: Methods where ILNestingDepth is higher than 4 are hard to understand and maintain. Methods where ILNestingDepth is higher than 8 are extremely complex and should be split in smaller methods (except if they are automatically generated by a tool).


Related Link::
A simple trick to code better and to increase testability

After following the link and using there simple trick to adjust my code as follows the method was no longer deemed complex.
   1: public Cell GetCellByRegEx(string regularExpression)
   2:       {
   3:           Check.Require(this._xlsFile != null);
   4:           Check.Require(!string.IsNullOrEmpty(regularExpression));
   5:  
   6:           var colCount = this._xlsFile.ColCount;
   7:           var rowCount = this._xlsFile.RowCount;
   8:           var sheetcount = this._xlsFile.SheetCount;
   9:  
  10:           for (var s = 1; s < sheetcount; s++)
  11:           {
  12:               this._xlsFile.ActiveSheet = s;
  13:  
  14:               for (var r = 1; r <= rowCount; r++)
  15:               {
  16:                   for (var c = 1; c <= colCount; c++)
  17:                   {
  18:                       var v = this._xlsFile.GetCellValue(r, c);
  19:                       if (v == null)
  20:                       {
  21:                           continue;
  22:                       }
  23:                       var regex = new Regex(
  24:                           regularExpression,
  25:                           RegexOptions.IgnoreCase);
  26:                       var matches = regex.Matches(v.ToString());
  27:  
  28:                       if (matches.Count <= 0)
  29:                       {
  30:                           continue;
  31:                       }
  32:                       var cell = new Cell { Row = r, Column = c, Value = v.ToString() };
  33:  
  34:                       return cell;
  35:                   }
  36:               }
  37:           }
  38:  
  39:           return null;
  40:       }

Conclusion

I have been developing software for 20+ years and the tools just keep getting better and better.  If you have the time and the inclination to improve your existing architecture you owe it to yourself to take a look at this product.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Currently rated 1.0 by 1 people

  • Currently 1/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Agile | C#
Posted by Bryan on Saturday, August 09, 2008 4:29 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Latitude, Longitude, Bearing, Cardinal Direction, Distance, and C#

If you are looking for some examples of using latitude and longitude to get bearing and distance information with C# you have come to the right place.  If you want to get straight to the code and the download click here.

 

I usually try to blog about things that I am working on that also could be interesting to other developers.  Recently I have been working on an application that stores information about commercial buildings and there competition.  Each location has a latitude and longitude which is used to display there data on a map.

 

To visualize the end result I have added a picture below of an application that is using using ASP.Net, Virtual Earth, while calculating bearing and distance.  This was inspire by Alessandro Gallo article.  If you are interesting in building a Virtual Earth mash-up using ASP.NET this is a must read article.  When the user puts there mouse over a location a pop-up with the distance and bearing are shown.  The distance is in miles while the bearing is represented by its cardinal value or compass direction.

MapVirtualEarth

 

Calculating Distance between two points of Latitude and Longitude

The function below uses the Haversine formula to calculate the distance between the to coordinates and a enumeration to request the type of unit of length. 

 

   1: /// <summary>
   2: /// Calculates the distance between two points of latitude and longitude.
   3: /// Great Link - http://www.movable-type.co.uk/scripts/latlong.html
   4: /// </summary>
   5: /// <param name="coordinate1">First coordinate.</param>
   6: /// <param name="coordinate2">Second coordinate.</param>
   7: /// <param name="unitsOfLength">Sets the return value unit of length.</param>
   8: public static Double Distance(Coordinate coordinate1, Coordinate coordinate2, UnitsOfLength unitsOfLength)
   9: {
  10:  
  11:     var theta = coordinate1.Longitude - coordinate2.Longitude;
  12:     var distance = Math.Sin(coordinate1.Latitude.ToRadian()) * Math.Sin(coordinate2.Latitude.ToRadian()) +
  13:                    Math.Cos(coordinate1.Latitude.ToRadian()) * Math.Cos(coordinate2.Latitude.ToRadian()) *
  14:                    Math.Cos(theta.ToRadian());
  15:  
  16:     distance = Math.Acos(distance);
  17:     distance = distance.ToDegree();
  18:     distance = distance * 60 * 1.1515;
  19:  
  20:     if (unitsOfLength == UnitsOfLength.Kilometer)
  21:         distance = distance * _MilesToKilometers;
  22:     else if (unitsOfLength == UnitsOfLength.NauticalMiles)
  23:         distance = distance * _MilesToNautical;
  24:  
  25:     return (distance);
  26:  
  27: }
Originally the function was made with 4 double values representing the latitude and longitudes for each coordinate.  While unit testing I tested incorrect coordinates. I found myself adding ArgumentOutOfRangeExceptions directly into the distance function above.  I did not like the feeling of this so I encapsulated the throwing of the exceptions in a coordinate class.  This reduced the code for the distance function and made the code clearer.
   1: public class Coordinate
   2:    {
   3:        private double latitude, longitude;
   4:  
   5:        /// <summary>
   6:        /// Latitude in degrees. -90 to 90
   7:        /// </summary>
   8:        public Double Latitude
   9:        {
  10:            get { return latitude; }
  11:            set
  12:            {
  13:                if (value > 90) throw new ArgumentOutOfRangeException("value", "Latitude value cannot be greater than 90.");
  14:                if (value < -90) throw new ArgumentOutOfRangeException("value", "Latitude value cannot be less than -90.");
  15:                latitude = value;
  16:            }
  17:        }
  18:  
  19:        /// <summary>
  20:        /// Longitude in degree. -180 to 180
  21:        /// </summary>
  22:        public Double Longitude
  23:        {
  24:            get { return longitude; }
  25:            set
  26:            {
  27:                if (value > 180) throw new ArgumentOutOfRangeException("value", "Longitude value cannot be greater than 180.");
  28:                if (value < -180) throw new ArgumentOutOfRangeException("value", "Longitude value cannot be less than -180.");
  29:                longitude = value;
  30:            }
  31:        }
  32:    }

 

Here are some of the unit tests that for the coordinate class. 

   1: [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
   2:      public void CoordinateLatitudeGreater90() { var coordinate = new Coordinate() { Latitude = 100, Longitude = -90 }; }
   3:  
   4:      [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
   5:      public void CoordinateLatitudeLessN90() { var coordinate = new Coordinate() { Latitude = -91, Longitude = -90 }; }
   6:  
   7:      [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
   8:      public void CoordinateLongitudeGreater180() { var coordinate = new Coordinate() { Latitude = 90, Longitude = 190 }; }
   9:  
  10:      [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
  11:      public void CoordinateLongitudeLessN180() { var coordinate = new Coordinate() { Latitude = 90, Longitude = -190 }; }
Here is an example usage of the distance function.
   1: var distance = Helper.Distance(new Coordinate() { Latitude = 45, Longitude = 0 },
   2:                                new Coordinate() { Latitude = 0, Longitude = 45 }, UnitsOfLength.NauticalMiles);
   3:  
   4: Assert.AreEqual(3599.8653599999993d, distance, "");

Calculating Bearing and Cardinal Direction

First, I have to give thanks to wikipedia for explaining what a cardinal point was. I never really thought about it until I thought about writing this article.  So for all of you who don't already know the location on your compass that say, "N,S,E,W" are called cardinal points. I am not generally one for being a stickler for using the correct nomenclature, but since I went and looked it up,  you can benefit from it.

First things first, we need to create a function that takes two coordinates that returns a direction in degrees.  Here is where my decision to encapsulate the latitude and longitude values paid some dividends.  Now the code will check the latitude and longitude values before it evaluates this function.

   1: /// <summary>
   2:       /// Accepts two coordinates in degrees.
   3:       /// </summary>
   4:       /// <returns>A double value in degrees.  From 0 to 360.</returns>
   5:       public static Double Bearing(Coordinate coordinate1, Coordinate coordinate2)
   6:       {
   7:           var latitude1 = coordinate1.Latitude.ToRadian();
   8:           var latitude2 = coordinate2.Latitude.ToRadian();
   9:  
  10:           var longitudeDifference = (coordinate2.Longitude - coordinate1.Longitude).ToRadian();
  11:  
  12:           var y = Math.Sin(longitudeDifference) * Math.Cos(latitude2);
  13:           var x = Math.Cos(latitude1) * Math.Sin(latitude2) -
  14:                   Math.Sin(latitude1) * Math.Cos(latitude2) * Math.Cos(longitudeDifference);
  15:  
  16:           return (Math.Atan2(y, x).ToDegree() + 360) % 360;
  17:       }

 

Now that we have a function that will return the bearing in degrees we need to convert those degrees to there cardinal value.

An enumeration to store the cardinal points.

   1: public enum CardinalPoints { N, E, W, S, NE, NW, SE, SW }
A class to store the ranges used to evaluated the cardinal points.
   1: /// <summary>
   2: /// Class is used in a calculation to determin cardinal point enumeration values from degrees.
   3: /// </summary>
   4: private struct CardinalRanges
   5: {
   6:     public CardinalPoints CardinalPoint;
   7:     /// <summary>
   8:     /// Low range value associated with the cardinal point.
   9:     /// </summary>
  10:     public Double LowRange;
  11:     /// <summary>
  12:     /// High range value associated with the cardinal point.
  13:     /// </summary>
  14:     public Double HighRange;
  15: }
The function to evaluate and return the cardinal direction.
   1: /// <summary>
   2:        /// Method extension for Doubles. Converts a degree to a cardinal point enumeration.
   3:        /// </summary>
   4:        /// <returns>Returns a cardinal point enumeration representing a compass direction.</returns>
   5:        public static CardinalPoints ToCardinalMark(this Double degree)
   6:        {
   7:  
   8:            var CardinalRanges = new List<CardinalRanges>
   9:                       {
  10:                         new CardinalRanges {CardinalPoint = CardinalPoints.N, LowRange = 0, HighRange = 22.5},
  11:                         new CardinalRanges {CardinalPoint = CardinalPoints.NE, LowRange = 22.5, HighRange = 67.5},
  12:                         new CardinalRanges {CardinalPoint = CardinalPoints.E, LowRange = 67.5, HighRange = 112.5},
  13:                         new CardinalRanges {CardinalPoint = CardinalPoints.SE, LowRange = 112.5, HighRange = 157.5},
  14:                         new CardinalRanges {CardinalPoint = CardinalPoints.S, LowRange = 157.5, HighRange = 202.5},
  15:                         new CardinalRanges {CardinalPoint = CardinalPoints.SW, LowRange = 202.5, HighRange = 247.5},
  16:                         new CardinalRanges {CardinalPoint = CardinalPoints.W, LowRange = 247.5, HighRange = 292.5},
  17:                         new CardinalRanges {CardinalPoint = CardinalPoints.NW, LowRange = 292.5, HighRange = 337.5},
  18:                         new CardinalRanges {CardinalPoint = CardinalPoints.N, LowRange = 337.5, HighRange = 360.1}
  19:                       };
  20:  
  21:  
  22:            if (!(degree >= 0 && degree <= 360))
  23:                throw new ArgumentOutOfRangeException("degree",
  24:                                                      "Degree value must be greater than or equal to 0 and less than or equal to 360.");
  25:  
  26:  
  27:            return CardinalRanges.Find(p => (degree >= p.LowRange && degree < p.HighRange)).CardinalPoint;
  28:  
  29:  
  30:        }
It seems like there could be a better way to check the value ranges but I could not think of one.  One thought was to use a simple array of values, but I concluded clearer larger code was better for long term readability.

Unit tests

Some basic unit tests to cover the code.
   1: /// <summary>
   2:    /// Summary description for UnitTest1
   3:    /// </summary>
   4:    [TestFixture]
   5:    public class Maps
   6:    {
   7:  
   8:        [Test]
   9:        public void DistanceSamePoint0()
  10:        {
  11:            var distance = Helper.Distance(new Coordinate() { Latitude = 90, Longitude = -90 },
  12:                                           new Coordinate() { Latitude = 90, Longitude = -90 }, UnitsOfLength.Mile);
  13:  
  14:            Assert.AreEqual(0, distance, "");
  15:  
  16:        }
  17:  
  18:        [Test]
  19:        public void DistanceSampleDataNauticalMiles()
  20:        {
  21:            var distance = Helper.Distance(new Coordinate() { Latitude = 45, Longitude = 0 },
  22:                                           new Coordinate() { Latitude = 0, Longitude = 45 }, UnitsOfLength.NauticalMiles);
  23:  
  24:            Assert.AreEqual(3599.8653599999993d, distance, "");
  25:        }
  26:  
  27:  
  28:        [Test]
  29:        public void DistanceSampleDataMiles()
  30:        {
  31:            var distance = Helper.Distance(new Coordinate() { Latitude = 45, Longitude = 0 },
  32:                                           new Coordinate() { Latitude = 0, Longitude = 45 }, UnitsOfLength.Mile);
  33:  
  34:            Assert.AreEqual(4145.3999999999996d, distance, "");
  35:        }
  36:  
  37:        [Test]
  38:        public void DistanceSampleDataKilometer()
  39:        {
  40:            var distance = Helper.Distance(new Coordinate() { Latitude = 45, Longitude = 0 },
  41:                                           new Coordinate() { Latitude = 0, Longitude = 45 }, UnitsOfLength.Kilometer);
  42:  
  43:            Assert.AreEqual(6671.3746175999995d, distance, "");
  44:        }
  45:  
  46:        [Test]
  47:        public void BearingsTests()
  48:        {
  49:            var bearing = Helper.Bearing(new Coordinate() { Latitude = 45, Longitude = 1 },
  50:                                         new Coordinate() { Latitude = 45, Longitude = 0 });
  51:  
  52:            Assert.AreEqual(270.35355787806577d, bearing, "");
  53:            Assert.AreEqual(CardinalPoints.W, bearing.ToCardinalMark());
  54:  
  55:        }
  56:  
  57:        [Test]
  58:        public void CardinalMarkValues()
  59:        {
  60:            Assert.AreEqual(CardinalPoints.N, 2D.ToCardinalMark());
  61:            Assert.AreEqual(CardinalPoints.NE, 46D.ToCardinalMark());
  62:            Assert.AreEqual(CardinalPoints.SE, 120D.ToCardinalMark());
  63:            Assert.AreEqual(CardinalPoints.S, 170D.ToCardinalMark());
  64:            Assert.AreEqual(CardinalPoints.SW, 220D.ToCardinalMark());
  65:            Assert.AreEqual(CardinalPoints.W, 273D.ToCardinalMark());
  66:            Assert.AreEqual(CardinalPoints.NW, 320D.ToCardinalMark());
  67:  
  68:        }
  69:  
  70:  
  71:  
  72:        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
  73:        public void ToCardinalMarkOutOfRange() { 390D.ToCardinalMark(); }
  74:  
  75:        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
  76:        public void CoordinateLatitudeGreater90() { var coordinate = new Coordinate() { Latitude = 100, Longitude = -90 }; }
  77:  
  78:        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
  79:        public void CoordinateLatitudeLessN90() { var coordinate = new Coordinate() { Latitude = -91, Longitude = -90 }; }
  80:  
  81:        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
  82:        public void CoordinateLongitudeGreater180() { var coordinate = new Coordinate() { Latitude = 90, Longitude = 190 }; }
  83:  
  84:        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
  85:        public void CoordinateLongitudeLessN180() { var coordinate = new Coordinate() { Latitude = 90, Longitude = -190 }; }
  86:  
  87:  
  88:    }

Summary

Hope this helps someone out there.  Let me know if there is anything I left out.

 

Bryan Reynolds

C# Developer

 

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Currently rated 5.0 by 4 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Bryan on Monday, June 02, 2008 12:01 AM
Permalink | Comments (3) | Post RSSRSS comment feed

C# Wrapping text using split and List<>

Below is a useful snippet of code to wrap text into a list of strings.  Download Click here.

 

Example

"The quick brown fox jumps over the lazy dog"

 

Lets say you need to fit this into a multi-line text box with a width or around 12 characters and an unlimited height.

 

The function will return a list of strings without splitting the individual words.

 

   1: var result = Wrap("The quick brown fox jumps over the lazy dog", 12);

 

result [0] = "The quick"

result [1] = "brown fox "

result [2] = "jumps over"

result [3] = "the lazy dog"

 

This function was used for reporting writing and formatting logs.

 

The function takes a string of any size and returns a list of string no larger than the max length input variable.

 

Let me know if this was useful.

   1: using System;
   2: using System.Collections.Generic;
   3:  
   4: /// <summary>
   5: /// Summary description for StringExtention
   6: /// </summary>
   7: public class StringExtention
   8: {
   9:     /// <summary>
  10:     /// Returns a list of strings no larger than the max length sent in.
  11:     /// </summary>
  12:     /// <remarks>useful function used to wrap string text for reporting.</remarks>
  13:     /// <param name="text">Text to be wrapped into of List of Strings</param>
  14:     /// <param name="maxLength">Max length you want each line to be.</param>
  15:     /// <returns>List of Strings</returns>
  16:     public static List<String> Wrap(string text, int maxLength)
  17:     {
  18:  
  19:         // Return empty list of strings if the text was empty
  20:         if (text.Length == 0) return new List<string>();
  21:  
  22:         var words = text.Split(' ');
  23:         var lines = new List<string>();
  24:         var currentLine = "";
  25:  
  26:         foreach (var currentWord in words)
  27:         {
  28:  
  29:             if ((currentLine.Length > maxLength) ||
  30:                 ((currentLine.Length + currentWord.Length) > maxLength))
  31:             {
  32:                 lines.Add(currentLine);
  33:                 currentLine = "";
  34:             }
  35:  
  36:             if (currentLine.Length > 0)
  37:                 currentLine += " " + currentWord;
  38:             else
  39:                 currentLine += currentWord;
  40:  
  41:         }
  42:  
  43:         if (currentLine.Length > 0)
  44:             lines.Add(currentLine);
  45:  
  46:         
  47:         return lines;
  48:     }
  49:  
  50:  
  51: }

 

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: C#
Posted by Bryan on Wednesday, May 07, 2008 11:04 AM
Permalink | Comments (4) | Post RSSRSS comment feed

Using LINQ to SQL instead of a sub report.

The post described how to use "Linq to SQL" with XtraReports and DevExpress for displaying relational data within a column of a report.

 

As a developer's we have all made many reports and used many tools to generate reports. Currently I am working with DevExpress's XtraReports Suite and "LINQ to SQL".  For web based relational database system reporting there tools are pretty easy to work with. 

 

Below is a sample output from a report that I am working on.  The interesting challenge was the 1 to many relationship within the Competitor column.

 

  XtraReport1

 

The competitor column needs to report all competitors from a 1 to many relationship table. There are many possible solutions to this common problem.  Using XtraReports you can make a subreport, you could set the text of the control by pulling the data from the database, or you could have a stored procedure format that data in the SQL engine you use prior to printing the report.

 

I chose to use "LINQ to SQL" for its quick implementation and ease of use.  If you have not had a chance to look at this technology take a look at Scott Gu's post.

 

In shorts order I was able to have a strongly type set of code that loaded a string with the exact format I needed to solve the problem.

   1: private void Detail_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e)
   2:    {
   3:        var projectID = Convert.ToInt32(GetCurrentColumnValue("ProjectID"));
   4:        var db = new dbDataContext();
   5:  
   6:        var queryCompitetion = from recs in db.ProjectCompetitions
   7:                               join comprecs in db.Competitions on recs.CompetitionID equals comprecs.CompetitionID
   8:                               where recs.ProjectID == projectID
   9:                               select new
  10:                                          {
  11:                                              recs.Distance,
  12:                                              recs.Direction,
  13:                                              comprecs.Name,
  14:  
  15:                                          };
  16:  
  17:        var stringBuiler = new StringBuilder();
  18:  
  19:        for (int i = 0; i < queryCompitetion.ToList().Count-1; i++)
  20:        {
  21:            var recs = queryCompitetion.ToList()[i];
  22:            stringBuiler.AppendFormat("{0}/ {1}{2}    ", recs.Name, recs.Distance, recs.Direction);
  23:  
  24:            if ((i + 1) % 2 == 0) stringBuiler.Append("\r\n");
  25:        }
  26:  
  27:        
  28:        xrCompetitorCell.Text = stringBuiler.ToString();
  29:    }

 

The "Detail_BeforePrint" function fires off before each report detail line is displayed.   Using the GetCurrentColumnValue function I retrieved the ProjectID for the current line.  Used "Linq to SQL" to grab the appropriate data using strong typing.  Iterated through the result and add the formatted string to the "xrCompetitorCell".  The "xrCompetitorCell" is a property of the report and generated via DevExpress's designer.

 

Hope this was useful from you.

 

Bryan

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Bryan on Wednesday, April 30, 2008 7:21 AM
Permalink | Comments (1) | Post RSSRSS comment feed

Interesting article about the new C# "var"

Ilya Ryzhenkov, a .NET Tools Product Manager at JetBrains, relays some of his thoughts on the var keyword here.

If you had a chance to use some of the latest c# language features you have no doubt heard of var.  Coming from the idea of KISS, keep it simple stupid, I not only agree with Ilya, but would say that this is the way it should have always been.  Especially now that we are in the day of IDE's and IDE addon's like JetBrain's resharper we should be reducing the amount of code we need to maintain and making the syntax easier to read.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: C#
Posted by Bryan on Wednesday, April 23, 2008 11:58 AM
Permalink | Comments (0) | Post RSSRSS comment feed