Aug
18
2005

Codezone search integration in Visual Studio 2005 !!! Cooool stuf :-)

As previously announced in this post: "Microsoft Announces CodeZone!",  Tech Head Brothers, my French portal about Microsoft .NET technologies, will be part of Codezone.  Today for the first time I am able to see what this means to be a part of the Codezone program.

As you can see in the option dialog of the Visual Studio 2005 help, you will be able to choose from a list of currently 28 world wide community web sites (we are 32nd - at the end, as far as I can remember).

And Tech Head Brothers is in the list. Great!!!

When doing a search you will get results from the various community sites that participate in Codezone.
For example a search about gzip returns two articles from Tech Head Brothers: one from me and one from Mathieu.

This has been in place for a while but had not been working on my VPC because (Thanks Doug ;) my clock was not set correctly. It has to be set within 7 minutes of the corresponding time i.e. present time.

For more information on what I am talking about read: "What is Codezone Community Search?"

Apr
9
2005

Visual Studio 2005, Team Foundation (aka Whidbey) Beta 2 will be here on the 25 of April

What can you expect from the Beta Experience?

  • Visual Studio 2005 Team System Beta 2
  • Team Foundation Server Beta 2
  • WeFly247 training DVD
  • SQL Server 2005 Standard Edition Community Technology Preview
  • The Beta Experience newsletter (6-weekly, terminated with the launch of the final version of Visual Studio 2005)

I hope that this time Team Foundation can be installed on one VPC.

Updated: The information is comming from this page: The Beta Experience (Thanks Alex).

Mar
12
2005

Refactoring the set of Predicate with an Interpreter

This evening I continued my journey with the C# Generics. I refactored what I described in my post "DataAccessLayer.FindAll(PublishedBy(Author)) " to be able to use the Design Pattern Interpreter.

The result in the ASPX code behind file is the following:

  1 AndSpec spec = new AndSpec(
  2                         new AndSpec(
  3                             new PublishedSpec(),
  4                             new BeforeDateSpec(DateTime.Parse("01/01/2005"))
  5                         ),
  6                         new OrSpec(
  7                             new AuthorSpec("Mathieu Kempé"),
  8                             new AuthorSpec("Laurent Kempé")
  9                         )
 10                     );
 11 
 12 DataAccessor<Article> articles = new DataAccessor<Article>("GetArticles");
 13 GridView3.DataSource = articles.FindAll(Matching(spec));
 14 GridView3.DataBind();
With the unique Matching Predicate, replacing all the other Predicate:
  1 protected Predicate<Article> Matching(Spec spec)
  2 {
  3 	return delegate(Article a)
  4 	{
  5 		return spec.isSatisfiedBy(a);
  6 	};
  7 }

To achieve this I first added two more properties to my Entity, Article. I did not added new constructors because those two properties are not mandatory:

  1 private DateTime datePublished;
  2 
  3 public DateTime DatePublished
  4 {
  5 	get { return datePublished; }
  6 	set { datePublished = value; }
  7 }
  8 
  9 private DateTime dateModified;
 10 
 11 public DateTime DateModified
 12 {
 13 	get { return dateModified; }
 14 	set { dateModified = value; }
 15 }
Then I modified my Data Access Layer to have it a bit more generic, starting with the interface :
  1 interface IDataAccess<T>
  2 {
  3 	List<T> GetAll();
  4 
  5 	List<T> FindAll(Predicate<T> match);
  6 }
  7 
I removed the method "T Get(Guid uuid)" and "T Get(string uuid)" because that can be easily expressed with a Predicate.
I made a Generic implementation of my Data Access through a DataAccessor class:
  1 namespace TechHeadBrothers.Portal.DAL
  2 {
  3 	public class DataAccessor<T> : IDataAccess<T> where T : new()
  4 	{
  5 		List<T> list = null;
  6 
  7 		public DataAccessor(string sp)
  8 		{
  9 			readFromDatabase(sp);
 10 		}
 11 
 12 		#region Protected Methods
 13 
 14 		protected void readFromDatabase(string sp)
 15 		{
 16 			// Create Instance of Connection and Command Object
 17 			SqlConnection myConnection =
 18 				new SqlConnection(ConfigurationManager.ConnectionStrings["TechHeadBrothers"].ConnectionString);
 19 
 20 			SqlDataAdapter myCommand = new SqlDataAdapter(sp, myConnection);
 21 
 22 			// Mark the Command as a SPROC
 23 			myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
 24 
 25 			// Create and Fill the DataSet
 26 			DataSet ds = new DataSet();
 27 			myCommand.Fill(ds);
 28 
 29 			myConnection.Close();
 30 
 31 			this.list = DataAdapterFactory.createAdapter<T>().Adapt(ds.Tables[0]);
 32 		}
 33 
 34 		#endregion
 35 
 36 		#region IDataAccess<T> Members
 37 
 38 		public List<T> GetAll()
 39 		{
 40 			return list;
 41 		}
 42 
 43 		public List<T> FindAll(Predicate<T> match)
 44 		{
 45 			return list.FindAll(match);
 46 		}
 47 
 48 		#endregion
 49 	}
 50 }
 
I had to implement an Adapter to convert the data from the Database representation to the Entity :
 
  1 abstract class DataAdapter<T> 
  2 {
  3 	public List<T> Adapt(DataTable table)
  4 	{
  5 		List<T> list = new List<T>(table.Rows.Count);
  6 
  7 		foreach (DataRow row in table.Rows)
  8 		{
  9 			list.Add(this.Adapt(row));
 10 		}
 11 
 12 		return list;
 13 	}
 14 
 15 	public abstract T Adapt(DataRow row);
 16 }
 
And a Factory :
 
  1 class DataAdapterFactory
  2 {
  3     public static DataAdapter<T> createAdapter<T>() where T : new()
  4     {
  5         string name = new T().GetType().Name.ToLower();
  6 
  7         if ( name == "article")
  8             return new ArticleAdapter() as DataAdapter<T>;
  9         else if ( name == "author")
 10             return new AuthorAdapter() as DataAdapter<T>;
 11 
 12         return null;
 13     }
 14 }
 
Here is the concrete implementation for the Article Entity Adapter:
 
  1 class ArticleAdapter : DataAdapter<Article>
  2 {
  3     public override Article Adapt(DataRow row)
  4     {
  5         Article article = new Article((string)row["Title"],
  6                                       (string)row["Description"],
  7                                       (string)row["Author"],
  8                                         (bool)row["isPublished"],
  9                                         (Guid)row["uuid"]);
 10 
 11         if (row["DatePublished"] != DBNull.Value)
 12         {
 13             article.DatePublished = (DateTime)row["DatePublished"];
 14         }
 15 
 16         if (row["DateModified"] != DBNull.Value)
 17         {
 18             article.DateModified = (DateTime)row["DateModified"];
 19         }
 20 
 21         return article;
 22     }
 23 }
 
I made also a Business Layer generic class, but has it is just for the moment a wrapper around the DataAccessor, I will not show it.
 
And finally the Interpreter Design Pattern:
 
  1 public abstract class Spec
  2 {
  3 	public abstract bool isSatisfiedBy(Article article);
  4 }
With the different concrete Specifications:
  1 public class PublishedSpec : Spec
  2 {
  3 	public PublishedSpec()
  4 	{
  5 	}
  6 
  7 	public override bool isSatisfiedBy(Article article)
  8 	{
  9  		return (article.isPublished == true);
 10 	}
 11 }
 12 
 13 public class BeforeDateSpec : Spec
 14 {
 15 	private DateTime date;
 16 
 17 	public DateTime Date
 18 	{
 19 		get { return date; }
 20 		set { date = value; }
 21 	}
 22 
 23 	public BeforeDateSpec(DateTime date)
 24 	{
 25 		this.Date = date;
 26 	}
 27 
 28 	public override bool isSatisfiedBy(Article article)
 29 	{
 30 		return (article.DatePublished < this.Date);
 31 	}
 32 }
 33 
 34 public class AuthorSpec : Spec
 35 {
 36 	private string author;
 37 
 38 	public string Author
 39 	{
 40 	  get { return author;}
 41 	  set { author = value; }
 42 	}
 43 
 44 	public AuthorSpec (string author)
 45 	{
 46 		this.Author = author;
 47 	}
 48 
 49 	public override bool isSatisfiedBy(Article article)
 50 	{
 51  		return (article.Author == this.Author);
 52 	}
 53 }
 54 
 55 public class NotSpec : Spec
 56 {
 57 	private Spec specToNegate;
 58 
 59 	public NotSpec(Spec specToNegate)
 60 	{
 61 		this.specToNegate = specToNegate;
 62 	}
 63 
 64 	public override bool isSatisfiedBy(Article article)
 65 	{
 66 		return !specToNegate.isSatisfiedBy(article);
 67 	}
 68 }
 69 
 70 public class AndSpec : Spec
 71 {
 72 	private Spec augend;
 73 	public Spec Augend
 74 	{
 75 	  get { return augend;}
 76 	}
 77 
 78 	private Spec addend;
 79 	public Spec Addend
 80 	{
 81 	  get { return addend;}
 82 	}
 83 	
 84 	public AndSpec (Spec augend, Spec addend)
 85 	{
 86 		this.augend = augend;
 87 		this.addend = addend;
 88 	}
 89 
 90 	public override bool  isSatisfiedBy(Article article)
 91 	{
 92  		return Augend.isSatisfiedBy(article) && Addend.isSatisfiedBy(article);
 93 	}
 94 }
 95 
 96 public class OrSpec : Spec
 97 {
 98 	private Spec augend;
 99 	public Spec Augend
100 	{
101 		get { return augend; }
102 	}
103 
104 	private Spec addend;
105 	public Spec Addend
106 	{
107 		get { return addend; }
108 	}
109 
110 	public OrSpec(Spec augend, Spec addend)
111 	{
112 		this.augend = augend;
113 		this.addend = addend;
114 	}
115 
116 	public override bool isSatisfiedBy(Article article)
117 	{
118 		return Augend.isSatisfiedBy(article) || Addend.isSatisfiedBy(article);
119 	}
120 }
Mar
10
2005

DataAccessLayer.FindAll(PublishedBy(Author))

One of the first development rule is to write human readable code. Why ? To avoid to have to write comments ;-) Because it will be read as a spoken language and it separate important code from distracting one.

What do you think about that line of code:

return DAL.FindAll(PublishedBy(Author));

Someone that has no clue about development might even read that code. Ok except the DAL word ;-)

With C# 2.0 you are able to write readable code like this using Generics, and the power of closures. In C# 2.0 closure are supported through the form of anonymous delegates.

Check out the different methods returning collection accordign to predefined rules: getAllUnpublished(), getAllPublished(), getAllPublishedBy()... There are all using Predicate, so to say anonymous delegate, that gives you human readable code.

Client code:

  1 protected void Page_Load(object sender, EventArgs e)
  2 {
  3 	GridView2.DataSource = TechHeadBrothers.Portal.BLL.ArticleBLL.getAllPublishedBy("Laurent Kempé");
  4 	GridView2.DataBind();
  5 
  6 	GridView3.DataSource = TechHeadBrothers.Portal.BLL.ArticleBLL.getAllWaitPublishingBy("Laurent Kempé");
  7 	GridView3.DataBind();
  8 }

The Business Layer:

  1 #region Using
  2 
  3 using System;
  4 using System.Collections.Generic;
  5 using System.Text;
  6 using TechHeadBrothers.Portal.Entities;
  7 using TechHeadBrothers.Portal.DAL; 
  8 
  9 #endregion
 10 
 11 namespace TechHeadBrothers.Portal.BLL
 12 {
 13 	public static class ArticleBLL
 14 	{
 15 		static ArticleDAL DAL = new ArticleDAL();
 16 
 17 		public static List<Article> getAll()
 18 		{
 19 			return DAL.GetAll();
 20 		}
 21 
 22 		public static List<Article> getAllUnpublished()
 23 		{
 24 			return DAL.FindAll(NotPublished());
 25 		}
 26 
 27 		public static List<Article> getAllPublished()
 28 		{
 29 			return DAL.FindAll(Published());
 30 		}
 31 
 32 		public static List<Article> getAllPublishedBy(string Author)
 33 		{
 34 			return DAL.FindAll(PublishedBy(Author));
 35 		}
 36 
 37 		public static List<Article> getAllWaitPublishingBy(string Author)
 38 		{
 39 			return DAL.FindAll(WaitPublishingBy(Author));
 40 		}
 41 
 42 		protected static Predicate<Article> WaitPublishingBy(string author)
 43 		{
 44 			return delegate(Article a)
 45 			{
 46 				return !a.isPublished && (a.Author.ToLower() == author.ToLower());
 47 			};
 48 		}
 49 
 50 		protected static Predicate<Article> PublishedBy(string author)
 51 		{
 52 			return delegate(Article a)
 53 			{
 54 				return a.isPublished && (a.Author.ToLower() == author.ToLower());
 55 			};
 56 		}
 57 
 58 		protected static Predicate<Article> Published()
 59 		{
 60 			return delegate(Article a)
 61 			{
 62 				return a.isPublished;
 63 			};
 64 		}
 65 
 66 		protected static Predicate<Article> NotPublished()
 67 		{
 68 			return delegate(Article a)
 69 			{
 70 				return (!a.isPublished);
 71 			};
 72 		}
 73 	}
 74 }
 75 

The Entity class is represented as:

  1 #region Using
  2 
  3 using System;
  4 using System.Collections.Generic;
  5 using System.Text; 
  6 
  7 #endregion
  8 
  9 namespace TechHeadBrothers.Portal.Entities
 10 {
 11 	public class Article
 12 	{
 13 		private Guid uuid;
 14 
 15 		public Guid Uuid
 16 		{
 17 			get { return uuid; }
 18 			set { uuid = value; }
 19 		}
 20 
 21 		private string title;
 22 
 23 		public string Title
 24 		{
 25 			get { return title; }
 26 			set { title = value; }
 27 		}
 28 
 29 		private string description;
 30 
 31 		public string Description
 32 		{
 33 			get { return description; }
 34 			set { description = value; }
 35 		}
 36 
 37 		private bool ispublished;
 38 
 39 		public bool isPublished
 40 		{
 41 			get { return ispublished; }
 42 			set { ispublished = value; }
 43 		}
 44 
 45 		private string author;
 46 
 47 		public string Author
 48 		{
 49 			get { return author; }
 50 			set { author = value; }
 51 		}
 52 
 53 		public Article(Guid uuid, string title, string description, string author)
 54 		{
 55 			this.Uuid = uuid;
 56 			this.Title = title;
 57 			this.Description = description;
 58 			this.isPublished = false;
 59 			this.Author = author;
 60 		}
 61 
 62 		public Article(string uuid, string title, string description, string author)
 63 			: this(new Guid (uuid), title, description, author)
 64 		{
 65 
 66 		}
 67 
 68 		public Article(string title, string description, string author)
 69 			: this(Guid.NewGuid(), title, description, author)
 70 		{
 71 
 72 		}
 73 	}
 74 } 

And the Data Access Layer Article class:

  1 #region Using
  2 
  3 using System;
  4 using System.Collections.Generic;
  5 using System.Text;
  6 
  7 #endregion
  8 
  9 namespace TechHeadBrothers.Portal.DAL
 10 {
 11 	interface IDataAccess<T>
 12 	{
 13 		T Get(Guid uuid);
 14 
 15 		T Get(string uuid);
 16 
 17 		List<T> GetAll();
 18 
 19 		List<T> FindAll(Predicate<T> match);
 20 	}
 21 
 22 	public class ArticleDAL : IDataAccess<TechHeadBrothers.Portal.Entities.Article>
 23 	{
 24 		List<TechHeadBrothers.Portal.Entities.Article> articles;
 25 
 26 		public ArticleDAL(List<TechHeadBrothers.Portal.Entities.Article> articles)
 27 		{
 28 			this.articles = articles;
 29 		}
 30 
 31 		public ArticleDAL()
 32 		{
 33 			this.articles = new List<TechHeadBrothers.Portal.Entities.Article>();
 34 
 35 			//TODO: Remove this is just for test
 36 			this.articles.Add(
 37 				new TechHeadBrothers.Portal.Entities.Article("Les generics dans C#",
 38 				"Démonstration de l'utilisation des générics dans C# 2.0",
 39 				"Laurent Kempé"));
 40 
 41 			TechHeadBrothers.Portal.Entities.Article article =
 42 				new TechHeadBrothers.Portal.Entities.Article("8BF7FEBE-9FEB-4db6-86B7-70A6C44B1CAA",
 43 				"Les iterators dans C#",
 44 				"Démonstration de l'utilisation des iterators dans C# 2.0",
 45 				"Laurent Kempé");
 46 			article.isPublished = true;
 47 			this.articles.Add(article);
 48 		}
 49 
 50 		#region IDataAccess<Article> Members
 51 
 52 		public TechHeadBrothers.Portal.Entities.Article Get(Guid uuid)
 53 		{
 54 			for (int i = 0; i < articles.Count; i++)
 55 			{
 56 				if (articles[i].Uuid == uuid)
 57 				{
 58 					return articles[i];
 59 				}
 60 			}
 61 
 62 			return null;
 63 		}
 64 
 65 		public TechHeadBrothers.Portal.Entities.Article Get(string uuid)
 66 		{
 67 			return this.Get(new Guid(uuid));
 68 		}
 69 
 70 		public List<TechHeadBrothers.Portal.Entities.Article> GetAll()
 71 		{
 72 			return articles;
 73 		}
 74 
 75 		public List<TechHeadBrothers.Portal.Entities.Article> FindAll(Predicate<TechHeadBrothers.Portal.Entities.Article> match)
 76 		{
 77 			return articles.FindAll(match);
 78 		}
 79 
 80 		#endregion
 81 	}
 82 }
 83 

[ Currently Playing : Sound Enforcer / Impact - Carl Cox (04:10) ]

Mar
3
2005

Conversion from Visual Studio .Net 2003 to Visual Studio 2005

This evening (hum morning ;) I decided to give a try to the conversion wizard integrated in Visual Studio 2005 that let you import older 1.1 projects.
I choosed to import my whole website: Tech Head Brothers. You might see next the conversion report:

And the Error List report of a build :

I am impressed about the conversion. Ok I have 2 errors and 133 Warnings, but the warnings are all due to deprecated classes or obsolete methods and the two errors are:

  • Error 134 Program '\Projects\Tech Head Brothers Portal\Database\obj\Debug\Database.exe' does not contain a static 'Main' method suitable for an entry point Database
  • Error 135 Program '\Projects\Tech Head Brothers Portal\Docs\obj\Debug\Docs.exe' does not contain a static 'Main' method suitable for an entry point Docs

Next step is to get the DB in SQL Server 2005 and make some tests. But that the task for another day.

Tomorrow I will be at the French DevDays 2005 in Strasbourg, hope to meet you there.

Nov
7
2004

Microsoft Tools for Domain Specific Languages Technology Preview (October 2004 Release)

"Today, you can download a tool that you can use to describe the concepts in a problem domain as the basis for a modeling tool or graphical designer. It is itself a graphical tool built on top of our designer platform and it is completely integrated into Visual Studio. For example, if you need a business process modeling tool, this editor allows you to describe the concepts specific to the way you like to model your business processes."

It is basically a graphical designer hosted in Visual Studio 2005 for designing and editing the concepts (or metamodel) of visual domain specific languages.

There is also an interesting : "Walkthrough of the Microsoft Tools for Domain Specific Languages" showing the use of the object model for a user interaction process (UIP) chart language. UIP chart defines pages and transitions between them as part of the design of a Web site, a wizard, or a form-based application. Figure 1 is an example of a UIP chart for a fictitious online shopping Web site. You might find more information on this page about the User Interface Process (UIP) Application Block - Version 2.0.

Read more about it on MSDN, on the Domain Specific Language (DSL) Tools page.
Download the tool, on Microsoft® Tools for Domain Specific Languages Technology Preview October 2004 Release page.

Oct
14
2004

Not such a sad day :-)

I knew I read it somewhere !!! Latest release of Whidbey permits to hide the components on the designer. Use the View menu Non Visual Controls, shortcut Ctrl+Shift+N.

A sad day for component developers

A couple months ago I posted about a major regression happening in ASP.NET v2. It's amazing that even after an overwhelming difference of 10 to 1 people voting to keep the Components tray in the designer, which allowed wizards, designer verbs, and extender providers to provide an incredible powerful enhanced visual experience in the IDE, Microsoft decided not to fix it.

So, you can kiss bye-bye to your UI-technology agnostic components and IDE integration. You'll have to keep two codebases and use the ugly gray-rendered "controls" (can't understand why you have to inherit from Control or WebControl if you're not doing any UI stuff, and why it has to live in the HTML design surface). A huge step backwards in what seemed to me like an important evolutionary step towards software factories based on highly reusable components.

They definitely ruined my day. But I plan to publish an extensive article of what you'll lose, and all the features you can exploit from this powerful model. Hopefully, if I get enough developers to use it, they will put more effort in bringing it back.

Aug
27
2004

Visual Studio 2005 Beta 1 refresh with the Team System

It seems that we will be updated on Whidbey :-) Nice. I will add to my development an evoluation of the Team System tools.

Visual Studio 2005 Beta 1 refresh with Team System

Rick LaPlante announced an upcoming refresh to the Visual Studio Community Technology Preview:

Jul
29
2004

An Introduction to the XML Tools in Visual Studio 2005

Msdn published an interesting article concerning the new XML possibilities of the IDE Visual Studio 2005.

Summary:

  • Checks the well-formedness errors in the XML and provides live feedback using red squiggly under the sequence of characters that is the cause of the errors and  through the error list.
  • XML File using schema are validated at design time and  the XML editor provides context-sensitive Intellisense.
  • Inferring a Schema from an XML Document The inferred schema is the most restrictive it can be, based on the XML used to infer it.
  • Attaching an XML Schema to an XML Document The user already has the schema and an XML file, and now needs to figure out how to associate the two.
  • Editing XSLT XSLT errors and standard XML syntax errors are displayed with the red squigglies and in the Error List.  Intellisense. Intellisense list is also sensitive to the namespaces that are being used.
  • Debugging XSLT Files from the XML Editor itself, or from a CLR language program that uses an XSLTCommand object from System.XML.

The debugging part for the XSLT and intellisense are really cool features.

About Laurent

Laurent Kempé

Laurent Kempé is the editor, founder, and primary contributor of Tech Head Brothers, a French portal about Microsoft .NET technologies.

He is currently employed by Innoveo Solutions since 10/2007 as a Senior Solution Architect and certified Scrum Master.

Founder, owner and Managing Partner of Jobping, which provides a unique and efficient platform for connecting Microsoft skilled job seekers with employers using Microsoft technologies.

Laurent was awarded Most Valuable Professional (MVP) by Microsoft from April 2002 to April 2012.

JetBrains Academy Member
Certified ScrumMaster
My status

Twitter

Flickr

www.flickr.com
This is a Flickr badge showing public photos and videos from Laurent Kempé. Make your own badge here.

Month List

Page List