BizTalk complaining about Orchestration instances still existing
As I was studying BizTalk 2006 R2, I came across a strange error. This error was reported by Visual Studio 2005 when trying to redeploy.
Could not change the bindings for orchestration ‘xxx’, Version=1.0.0.0,Culture=neutral, PublicKeyToken=c380e04620d206e8′ as one or more instances of the orchestration still exist.
Trying to act on the orchestration itself or even the solution in BizTalk Administration Tool was giving the same error.
The fix was found in this blog post: One or more instances of the orchestration still exist.
So, there are two solutions to fix this issue:
- Terminate instances manually using the BizTalk Administration Tool, which didn’t work for me.
- Use a stored procedure to clear BizTalk’s message box of all messages. This one didn’t work either.
As pointed out in one of the comments of the abode post, the bts_CleanupMsgbox comes empty at BizTalk install. This means that it executes when you call it, but nothing happens. The orchestrations were still in the list of running orchestrations in BizTalk Administration Tool.
However, the script to create the working procedure is located in the "C:\Program Files\Microsoft BizTalk Server 2006\Schema\msgbox_cleanup_logic.sql" file. Once this has been executed, the stored procedure will correctly clean BizTalk’s messages database.
LINQ to SQL and auto increment fields
When using LINQ to SQL in Visual Studio 2005, Table and Column mapping has to be coded manually. This is not a very difficult job but it’s repetitive and boring (of course, if you are using Visual Studio 2008 to automatically generated the mapping code, this will be done automatically).
I ran into an issue while following a guide on manually map database tables to classes. When I tried to insert a new record, leaving the identity field empty in the object, I had the following error:
"Cannot insert explicit value for identity column in table ‘Contexts’ when IDENTITY_INSERT is set to OFF."
It was pretty obvious that, as the identity column was and Int32, it was set to 0 as default, and when LINQ tried to insert that row in the table the SQL Server raised an error as this auto incremented field cannot be explicitly set.
This is simply solved by using the IsDbGenerated attribute in the Column annotation description of the field, as shown in the following code.
private Int32 _id; [Column(IsPrimaryKey = true, IsDbGenerated = true)] public Int32 Id { get { return this._id; } set { this._id = value; } }
This attribute tells LINQ not to give a value for this field as it is generated by the database at insert time.
Another very nice thing about this is that once you have inserted the object in the database, this field will hold the value generated by the database. Practically, this means that after executing the following code
DataTable.InsertOnSubmit(obj); DataContext.SubmitChanges();
the obj.Id property will contain the value that was assigned by the database.
LINQ in Visual Studio 2005
A few months ago, we wanted to query an XML log file on our project. On that particular project, we can use .NET 3.5 features, while we have to stick to Visual Studio 2005.
For this task, LINQ seemed like a natural choice, provided that we could use it inside Visual Studio 2005 which doesn’t natively support the sexy LINQ query syntax.
At first, we thought that it was not possible to use LINQ in Visual Studio 2005, but after some research it turned out that we were wrong. I found some clues on how to achieve that in one of the comments on this post comment by Charles Young.
The LINQ libraries are located in the System.Core assembly, so it is required to reference it in the project. Then, each file that will use LINQ will have to include the System.Linq using statement.
A simple LINQ query
Let’s take a standard LINQ query on a String array
String[] persons = new String[] { "Philippe", "Steve", "Bill" }; var search = from p in persons where p.Contains("l") select p.ToUpper();
This is a fairly simple query, involving only filtering (where clause) an projection (select with transformation of the output). This native query will be translated by the compiler multiple times, we just have to follow the pipeline until we find something that Visual Studio 2005 understands.
The first translation results in a statement that uses Extensions methods on the array:
var search = persons .Where(p => p.Contains("l")) .Select(p => p.ToUpper());
These extension methods are from Enumerable class. However, Extension methods are not natively supported in Visual Studio 2005.
The reverse call of the previous statement will be a use some of Enumerable’s static methods (as these are Extension methods, the reverse call will actually call a static method and give the object that you think it has been called on as parameter). In this particular example, it will be translated in:
var search = Enumerable.Select( Enumerable.Where(persons, p => p.Contains("l")), p => p.ToUpper());
Please note that this translation results in using Enumerable because for this particular case we are using LINQ to Objects. I suppose that using LINQ to SQL would result in using Queryable static methods, but I didn’t try yet.
Also note that there is a call to Enumerable.Select because our initial query involves projection, in a sense that the result of the query (here a String object) is different from the input (here a String object that is a transformation of the input). If the projection statement of the initial query was "select p" (no transformation of the output), there would be no call to Enumerable.Select. More on this below.
Still, this statement is not supported in Visual Studio 2005 because of the lambda expressions that are not supported.
The next step for the compiler is to translate these lambda expressions into anonymous delegates:
var search = Enumerable.Select( Enumerable.Where( persons, delegate(String p) { return p.Contains("l"); }), delegate(String p) { return p.ToUpper(); });
Even if this looks like something we could use in Visual Studio 2005, it is not. Visual Studio 2005 will complain because it is unable to infer types (and because of the var keyword that is also part of C# 3.0 hence not supported in Visual Studio 2005).
We have to specify types explicitly for the Enumerable methods:
IEnumerable<String> search = Enumerable.Select<String, String>( Enumerable.Where<String>( persons, delegate(String p) { return p.Contains("l"); }), delegate(String p) { return p.ToUpper(); });
There we are, a LINQ query that can be used inside Visual Studio 2005! It’s a bit confusing to write at first, but you’ll get use to it.
Now that we have seen a simple query, let’s have a look at the other query statements.
Ordering
Always using the same String array, here is the C# 3.0 style LINQ query
var search = from p in persons orderby p select p;
that translates in
IEnumerable<String> search = Enumerable.OrderBy<String, String>( persons, delegate(String p) { return p; });
As you can see, no need for Enumerable.Select call as the projection returns the same object.
If you want to order descending, use the Enumerable.OrderByDescending method instead. It is also possible to specify the IComparer that is to be used by the OrderBy/OrderByDescending method, thus allowing you to use ordering on custom object.
Joining
For joining, we need to define some struct in order do have two distinct list of elements.
So, here is a simple struct:
struct Name { public int Id; public String Value; public Name(int Id, String Value) { this.Id = Id; this.Value = Value; } }
And here are two array declarations:
Name[] firstNames = new Name[] { new Name(1, "Philippe"), new Name(2, "Steve"), new Name(3, "Bill") }; Name[] lastNames = new Name[] { new Name(1, "Vlérick"), new Name(2, "Balmer"), new Name(3, "Gates") };
Using two arrays, we will be joining on the Id field of the Name struct.
The C# 3.0 query:
var search = from fn in firstNames join ln in lastNames on fn.Id equals ln.Id select fn.Value + " " + ln.Value;
Here is the translation:
IEnumerable<String> search = Enumerable.Join<Name, Name, int, String>( firstNames, lastNames, delegate(Name n) { return n.Id; }, delegate(Name n) { return n.Id; }, delegate(Name n1, Name n2) { return n1.Value + " " + n2.Value; });
This one is a bit tricky and need some clarification.
The first two types given are the type of object that each collection contains. The third type is the type that the actual join will be made on and has to be the same on both collections. The last type is the type of the objects that will be stored in the returned collection. So, in this particular case, the first collection will contain Name objects, the second collection will contain Name objects as well, the join will be made on int types and the returning collection will contain String objects.
As parameters, the first two are collections that contain the object to use for the join. The next two parameters are the delegates that must return the type the join has to be made on (in this case, int). The first delegate will be used with each object of the first collection (in this case, firstNames) and the second delegate will be used with each object of the second collection (lastNames). The last parameter is a delegate that must return the given return type (here a String object) receiving the two joined objects as parameters).
Note that we don’t need to explicitly call the projection method (Enumerable.Select) as there is a selector delegate that builds the output object.
Grouping
As a reminder, grouping means splitting the output in sequences of groups that have the same key value. The output of this type of query is a bit different from the previous queries.
A custom struct is needed to have an example object that we can test grouping on:
struct Student { public String Name; public String Course; public Student(String Name, String Course) { this.Course = Course; this.Name = Name; } }
We can then declare an array that we will query on
Student[] students = new Student[] { new Student("Philippe", "Data Structure"), new Student("Bill", "Marketing"), new Student("Steve", "Finance"), new Student("Bill", "Data Structure"), new Student("Steve", "Dance"), new Student("Bill", "Finance") };
Lets group on Course field of the struct. Here is the C# 3.0 query:
var search = from s in students group s by s.Course;
As you can see, there is no projection. The output is a IEnumerable of IGrouping objects. An IGrouping object is a collection of objects that share a common key, in here Student objects with String as keys.
To iterate trough this, we need two foreach loops. the first one will iterate trough each IGrouping object, and the second one will iterate trough each Student.
foreach (var course in search) { Console.WriteLine(course.Key); foreach (var student in course) { Console.WriteLine("- " + student.Name); } }
This is how this query translates in Visual Studio 2005:
IEnumerable<IGrouping<String, Student>> search = Enumerable.GroupBy<Student, String>( students, delegate(Student s) { return s.Course; });
And the loops to display the content:
foreach (IGrouping<String, Student> course in search) { Console.WriteLine(course.Key); foreach (Student student in course) { Console.WriteLine("- " + student.Name); } }
Again, you have to specify types everywhere in Visual Studio 2005.
Other Thoughts
One of the other painful things with Visual Studio 2005 is that there are no anonymous types which are very handy to use with LINQ. It is required to write all the used types as Classes (or better, Structs).
Conclusion
Using static methods from Enumerable (and possibly Queryable), it is possible to use LINQ queries inside Visual Studio 2005. However, queries are a bit more complicated to write.
A good practice would be to comments the query intend extensively, as the query statement itself is hard to read.
Resources
Here are some of the resources I used to write this entry:
- Programming C# 3.0 – O’Reilly, January 2008
- "Linq To Anything" – Bart De Smet, March 2008
- "LINQ Under the Covers" – Alex Turner, March 2008
Visual Studio 2005 extensions for WCF and WPF installation after installing .NET 3.5
When .NET 3.0 was released, Microsoft provided a Visual Studio 2005 extension for WCF and WPF. This extension contains tools to ease development of these new technologies (for example, the Configuration Editor Tool that is quite useful to edit WCF configuration files).
If you are still using Visual Studio 2005, these tools are very useful (while not mandatory) to use .NET 3.0.
As I was reinstalling all my stuff on a new laptop, I started by installing .NET 3.5 SP1, then Visual Studio 2005. I only realized later that I forgot the WCF and WPF extensions for Visual Studio.
The first problem I encountered was that this extension is not available anymore on Microsoft’s web site. This is not a mistake, and the why is that Microsoft wants to encourage users to move to Visual Studio 2008. Nice, thanks guys. You can read the details here.
Anyway, it is not too difficult to find this download. I personally found it on ZDNet.
Running the installation, I ran into some issue. The installer complains that a prerequisite is missing:
Setup has detected that a prerequisite is missing. To use Visual Studio 2005 extensions for .NET Framework 3.0 (WCF & WPF), November 2006 CTP you must have the .NET Framework 3.0 runtime installed. Please install the .NET Framework 3.0 runtime and restart setup.
So, the installer is kind of dumb and checks that .NET 3.0 is installed, and only this precise version.
Once more, the solution is quite easy and can be found here.
The installer apparently checks for some registry key, so creating it is sufficient. The key is HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{15095BF3-A3D7-4DDF-B193-3A496881E003} under which a string value of "DisplayName"="Microsoft .NET Framework 3.0" is needed. In my case, I had to create the last directory too.
After that, the installer process complained about some documentation issues but still ran correctly. The registry key can safely be deleted after the install process.
Update: alternatively, you can run the following command in a DOS prompt:
msiexec /i vsextwfx.msi WRC_INSTALLED_OVERRIDE=1
This will display the same warning message about .NET 3.0, but you can still install after the warning.
