Thursday, June 24, 2010

Using Team Foundation Server 2010 from Visual Studio 2005 and 2008

On my project the TFS server has just been upgraded, ready for us to replatform the software onto .Net 4.0. In the meantime we're still working on a mixture of Visual Studio 2005 (for BizTalk 2006 R2) and Visual Studio 2008 (for the rest of the .Net and database code).

Team Foundation Server 2010 is not compatible with Visual Studio / Team Explorer 2005 and 2008 without the compatibility upgrade.

In order to install the compatibility pack for Visual Studio 2008 go here:


In order to install the compatibility for Visual Studio 2005 go here:


Workspace issues

Once you have connected to the new TFS server and mapped your projects back, you should be able to map your workspaces without any problems.

However, you might find that your workspaces do not work. This is especially an issue in Visual Studio 2005, which seems not to recognise the workspace that you have reapped the workspace. If this is the case, run the following command from the VS2005 Command Prompt:

tf.exe workspaces /remove:*

Then get latest on your source branch. It should be OK.

Tuesday, February 23, 2010

The endless debate on "what is an architect"

Just been following the following debate in LinkedIn: http://www.linkedin.com/groupAnswers?viewQuestionAndAnswers&discussionID=13839089&gid=100988&commentID=12211252&trk=view_disc

The discussion started with the following comment:

This is what is killing Enterprise Architecture…
Quote from "John Zachman" article..;-)
This is what is killing Enterprise Architecture… every computer programmer, systems designer, software architect, solutions architect, technology architect, computer operator, PC owner, data architect, database architect, network architect, business analyst, systems analyst, enterprise architect, service architect, object architect, project manager and CIO calls whatever they want to or maybe, whatever they are doing, “Architecture.” It is chaos. No wonder we don’t have Enterprises that are coherent, integrated, flexible, dynamic, interoperable, reusable, aligned, lean and mean and working.


And I thought I'd add my bit as well.....

I love this discussion, if only because it goes round in circles so much. Getting back to the original point though:

"....calls whatever they want to or maybe, whatever they are doing, “Architecture.”"

This gets to the nub of the problem. Quite simply, you are an architect if the role you perform is "architecture". However, people do indeed hijack the term to make their own role sound better. We cannot rely on some higher authority to define for us what an architect is and then impose a set of criteria to test against. Instead it is incumbent upon all of us who consider ourselves to be architects to explain what architecture involves and if we suspect others of "job title inflation" we should ask what they have done that qualifies as architecture.

As a marker, I think there are some fundamental aspects of architecture that we should be able to agree on:

* Architecture is a high-level design activity. The output of architecture is a design of some sort, although this can vary enormously in the level of abstraction. Architecture is the synthesis of a design that satisfies a set of requirements.

* A secondary activity of an architect is communication of the design and the supervision of the detailed design and implementation to ensure that the design intent has been captured.

* Another secondary activity of an architect is to communicate to those creating requirements what the impact of their requirements will be on the design and to advise on improvements.

Someone whose primary role is development / implementation / operations is not therefore an architect. I think "enterprise" architecture vs other types of architecture is a red herring in this regard. These are all valid disciplines - there are indeed "data architects", there are indeed "infrastructure architects" and there are indeed "enterprise architects". The key thing is that in each case the primary goal of their activity is design.


You've got to love it. I haven't seen a more circular debate since the old artists vs scientists one that you have at university!

Thursday, January 07, 2010

User-Defined Functions for Today and Tomorrow in SQL

Just a quick post today. I have been working on some bugs on a system were about to release, which was originally built by some dodgy developer before we took it over. The older reaches of the application are a total mishmash f things that should be in the database, data access layer, business logic layer and in the UI, so please don't flame me with comments like "you shouldn't be doing this in the database, it should be in the ......".

One of the features that I was fixing was a view that contains the current effective price for a product. Imagine that you have a table that contains prices, and when a price changes you insert a new row with the updated price and an effective date. Simple stuff - the current price is the one with the most recent effective date that is either today or in the past, i.e. before tomorrow.

Now, SQL server is a pain in the ass when it comes to simple date stuff like this, because all I want is something like this:

SELECT
TOP 1 *
FROM
ProductPrice
WHERE
ProductID = @ProductID
AND EffectiveDate <>
ORDER BY
EffectiveDate DESC

I therefore wrote a couple of functions to achieve this:

CREATE FUNCTION [dbo].[Today]()
RETURNS datetime
AS
BEGIN
DECLARE @today datetime;

SET @today = convert(datetime, convert(varchar(10),getdate(),101), 101);

RETURN @today;
END

CREATE FUNCTION [dbo].[Tomorrow]()
RETURNS datetime
AS
BEGIN
DECLARE @tomorrow datetime;

SET @tomorrow = convert(datetime, convert(varchar(10),getdate(),101), 101);
SET @tomorrow = DATEADD(d, 1, @tomorrow);

RETURN @tomorrow;
END


Enjoy :)

Wednesday, December 09, 2009

Note to Self: MQSeries

I've been off working on another project for a very busy 3 weeks (more on this perhaps in the next post) and have now returned back onto the project I was on since July.

This is a quick note to self for when the password on the service account for IBM MQSeries needs to be changed. When the password expired I got an error message like this when I tried to start a queue manager:

Initialization of resource 'amqmsrvn' failed, rc=0x8000401a
The server process could not be started because the configured identity is incorrect. Check the username and password.
exitvalue = -4


First, you need to change the service account / password on the IBM MQSeries windows service (from the Services MMC):

And second you need to go into Component Services (COM+) and find the "IBM MQSeries Services" in the DCOM Config node:

And then update the password in the "Log On" tab.


Hopefully I won't waste an hour rebuilding my queues next time!

Thursday, November 05, 2009

Use of generic types in BizTalk and XLANG/s

This is just a quick post to note down something that I have been explaining to people lately. The project I am working on at the moment has several teams of developers working together and most of the code is being cut in Visual Studio 2008 / .Net 3.5. As such, we in the BizTalk feature team are taking delivery of components coded in other teams and integrating them. We are using BizTalk 2006 R2 and developing the BizTalk orchestrations in Visual Studio 2005, although there are no compatability issues between the binaries developed in 2008 and 2005, and anyway generic types were introduced in 2005 / .Net 2.0.

However, where I have come across an issue is in the use of generic types, and specifically assigning generic types to orchestration variables. In some cases orchestrations and expression shapes support generics and in some cases they do not.

All I am going to do is to illustrate some cases where generics are OK and some where they are not, with a bit of explanation as to why.

Assigning to variables

Imagine that you have a class:

public class MyClass {}

And you want to use a collection of this class in your code, these days you would usually use a generic collection in our code:

Collection collection = new Collection<MyClass>();

However, if you try to assign this type to a variable in an orchestration you will find that you can't. This is because you can only pick from a type that is compiled, and generic types aren't in there. If you want to use a collection like this in an orchestration you will have to create a type for it. You can define a new class:

public class MyClassCollection : Collection<MyClass> {}

If you do this, you can reference "MyClassCollection" as a variable in your orchestration and everything will be fine. Note that the usual rules about classes being marked as serializable apply.

The same applies if you create a class that has a generic interface such as this:

namespace AndrewGenerics.Components
{
[
Serializable]
public class OrchestrationInstanceHelper<T>
{
public void UpdateInstance(T objectInstance)
{
// Some code in here
}
}
}

If you see this class in the type picker and try to assign it to a variable you will be able to pick it:

However you will not be able to assign the generic type:


As a result if you try to compile you will get a whole heap of errors like these:

Error 1 '` (0x60)': character cannot appear in an identifier C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 62 63
Error 2 '` (0x60)': character cannot appear in an identifier C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 67 80
Error 3 identifier 'OrchestrationInstanceHelper' does not exist in 'AndrewGenerics.Components'; are you missing an assembly reference? C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 62 36
Error 4 cannot find symbol 'AndrewGenerics.Components.OrchestrationInstanceHelper' C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 62 36
Error 5 expected 'identifier' C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 62 64
Error 6 unexpected token: 'numeric-literal' C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 62 64
Error 7 identifier 'helper' does not exist in 'TestOrchestration'; are you missing an assembly reference? C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 67 14
Error 8 cannot find symbol 'helper' C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 67 14
Error 9 identifier 'OrchestrationInstanceHelper' does not exist in 'AndrewGenerics.Components'; are you missing an assembly reference? C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 67 53
Error 10 cannot find symbol 'AndrewGenerics.Components.OrchestrationInstanceHelper' C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 67 53
Error 11 'new OrchestrationInstanceHelper': a new expression requires () after type C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 67 23
Error 12 expected 'identifier' C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 67 82
Error 13 unexpected token: '(' C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 67 82
Error 14 illegal statement '1' C:\Projects\AndrewGenerics\AndrewGenerics.BizTalk\TestOrchestration.odx 67 81

All those errors are because of a couple of things, but mainly because when you add a variable to an orchestration, or add code in an expression shape, the designer writes some C# code for you and then compiles it. Because the way that the designer handles generics is incorrect the C# doesn't compile and you get the build errors.

Again though, if you created a class that inherited from the above class and assigned the generic type you'd be OK:

public class MyClassInstanceHelper : OrchestrationInstanceHelper<MyClass> {}

Passing parameters to methods

OK. Let's now create a helper component that we will call from an orchestration. [Disclaimer: The code below if for illustration purposes only!]

namespace
AndrewGenerics.Components

{
public static class OrchestrationHelper
{

// Note that this uses the collection type
public static void UpdateItemsInCollection(MyClassCollection collection)
{
// Some code in here
}

// Note that this uses the generic type
public static void UpdateItemsInCollection2(IEnumerable<MyClass> collection)
{
// Some code in here }
}
}

The first of these calls uses the inherited type and so will go through no problem:

AndrewGenerics.Components.OrchestrationHelper.UpdateItemsInCollection(myCollection);

But even if we use the second of the method calls with the IEnumerable<MyClass> parameter, that still works OK:

AndrewGenerics.Components.OrchestrationHelper.UpdateItemsInCollection2(myCollection);

Therefore, even though the method in a helper component has a generic type in the code, when the class is compiled the generic type gets "baked" into the interface and so the variable assignment works.

Assigning output from methods to variables

Now let's add another method onto the helper class that we can use to receive a collection of objects, but again through a generic type.

public static IEnumerable<MyClass> GetCollection()
{
Collection<MyClass> coll = new Collection<MyClass>();

coll.Add(
new MyClass());

return coll;
}

In order to call this I might use a line of code like this in an expression shape:

myCollection = (AndrewGenerics.Components.MyClassCollection)AndrewGenerics.Components.OrchestrationHelper.GetCollection();

Again, this is handled OK by the BizTalk compiler when we are assigning to our collection and the we are casting the type of the result. For the same reasons as above, we can't create a variable of IEnumerable<MyClass;> so we can't receive the output of this method without casting it, but we can at least handle it. Obviously, if at runtime we were presented with a different object that conformed to IEnumerable<MyClass;> (such as an array) we would get a runtime error because of an invalid cast.

However, we have been able to declare a method that uses a generic type, and for the same reason we can use it, i.e. when the helper component is compiled the method signature becomes fixed and the orchestration compiler can handle the output.

Conclusions

Here are some key points from this blog post:

  1. You cannot declare generic type in an orchestration because you can only select types in the type picker. If you select a generic interface that does not have the type assigned you get some crazy errors.
  2. In order to use a generic type you can create a class that implements the generic type. This will then be usable by BizTalk.
  3. When a helper component uses generic types in the interface the types get baked into the interface and can be used by BizTalk.

Wednesday, November 04, 2009

Am I missing something?

I was shopping on Amazon for my son's Christmas present this afternoon. He wants a laptop and I was looking for an entry-level laptop that is running Windows 7. I found this nice looking Compaq Presario:



However, when I scrolled down on the description I found the following:


That's it. The only thing that other people have bought. I was expecting to see antivirus and MS Office! Just shows that you can't assume what choices the public will make!