Friday, October 31, 2008

Gacutil: Failure adding assembly to the cache: Unknown Error

Problem

Gacutil gives an error: "Failure adding assembly to the cache: Unknown Error" when adding assembly to the cache

Solution

Each version of .Net Framework contains own gacutil. If you are trying to add .net 2.0 assembly to the cache you must use .net Framework 2.0 gacutil, not 1.1 or 3.0 gacutil.

You can also manually copy assembly file to the cache. Cache is located at Windows\Assembly

Tuesday, October 28, 2008

Biztalk 2006: How to use Biztalk message in C# code

Problem

How to use a Biztalk message in C# code

Solution

1. Add reference to Microsoft.XLANGs.BaseTypes.dll which is inside Biztalk installation directory
2. Add using Microsoft.XLANGs.BaseTypes; to your class
3. Declare variable like this: XLANGMessage BiztalkMessage

Friday, October 24, 2008

C#: How to sort list of objects by multiple columns

Problem

How to sort list of objects by multiple columns in C#

Solution

Solution is to create a comparer class for objects. Comparer class can take multiple columns as parameter. If you want to use the list of objects as a DataSource for GridView in ASP.Net page you can store the list in ViewState and sort it as many times you want without asking data again from database

Here is the Product class I want to sort by multiple columns:


    public class Product
    {
        private string code;
        private string description;
        private double price;

        public double Price
        {
            get { return price; }
            set { price = value; }
        }

        public string Code
        {
            get { return code; }
            set { code = value; }
        }

        public string Description
        {
            get { return description; }
            set { description = value; }
        }

        public Product(string CodeValue, string DescriptionValue, double PriceValue)
        {
            Price = PriceValue;
            Code = CodeValue;
            Description = DescriptionValue;
        }

    }

And here is a SortColumn class which stores sort fields and what is used with comparer class:


   public class SortColumn
    {
        public enum sortOrderEnum
        {
            Descending = 0,
            Ascending = 1
        }

        private sortOrderEnum order;
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public sortOrderEnum Order
        {
            get { return order; }
            set { order = value; }
        }

        public SortColumn(string NameValue, sortOrderEnum OrderValue)
        {
            Name = NameValue;
            Order = OrderValue;
        }

    }

Next thing to do is write the generic object comparer class to sort one or multiple columns:


   public class GenericComparer<ComparableObject> : IComparer<ComparableObject>
    {

        private List<SortColumn> sortByColumns;

        public List<SortColumn> SortByColumns
        {
            get { return sortByColumns; }
            set { sortByColumns = value; }
        }

        public GenericComparer()
        {
        }

        public GenericComparer(List<SortColumn> SortByColumnsValue)
        {
            SortByColumns = SortByColumnsValue;
        }

        public int Compare(ComparableObject x, ComparableObject y)
        {
            if (sortByColumns != null)
            {
                // Loop through all sort fields
                foreach (SortColumn sortItem in sortByColumns)
                {
                    // Get information about property which is used as sort field
                    PropertyInfo propertyInfo = x.GetType().GetProperty(sortItem.Name);
                  
                    // Put null values to bottom of the list
                    if (propertyInfo.GetValue(x, null) == null)
                    {
                        return 1;
                    }
                    if (propertyInfo.GetValue(y, null) == null)
                    {
                        return -1;
                    }
                    

                    int compareResult = Comparer.DefaultInvariant.Compare(propertyInfo.GetValue(x, null), propertyInfo.GetValue(y, null));
                    if (compareResult != 0)
                    {
                        if (sortItem.Order == SortColumn.sortOrderEnum.Descending)
                        {
                            return -compareResult;
                        }
                        else
                        {
                            return compareResult;
                        }
                    }
                }
                return 0;
            }
            else
            {
                return 0;
            }
        }

    }

And for last thing create a console application to test how comparer class works:


    public class Program
    {
        public static void Main(string[] args)
        {

            // Create product list with data
            List<Product> products = new List<Product>();
            products.Add(new Product("123456", "Table", 1240.99));
            products.Add(new Product("000123", "Lamp", 25.10));
            products.Add(new Product("000124", "Lamp 2", 24.55));
            products.Add(new Product(null, "Sofa", 2499.00));
            products.Add(new Product("445405", "Bed", 1399.40));
            products.Add(new Product("345405", "Bed", 1499.40));

            // List of sort fields
            List<SortColumn> sortColumns = new List<SortColumn>();

            // Not sorted
            Console.WriteLine("Products in order of appearance:");
            ListProducts(products);

            // Sort by product code
            Console.WriteLine("Products ordered by Code:");
            sortColumns.Add(new SortColumn("Code", SortColumn.sortOrderEnum.Ascending));
            products.Sort(new GenericComparer<Product>(sortColumns));
            ListProducts(products);

            // Sort by description and code
            Console.WriteLine("Products ordered by Description and Code:");
            sortColumns.Clear();
            sortColumns.Add(new SortColumn("Description", SortColumn.sortOrderEnum.Ascending));
            sortColumns.Add(new SortColumn("Code", SortColumn.sortOrderEnum.Ascending));
            products.Sort(new GenericComparer<Product>(sortColumns));
            ListProducts(products);

            // Ready
            Console.ReadLine();

        }

        public static void ListProducts(List<Product> Products)
        {
            Console.WriteLine("");
            foreach (Product item in Products)
            {
                Console.WriteLine(item.Code + "\t" + item.Description + "\t" + item.Price.ToString());
            }
            Console.WriteLine("");
        }

    }

Now you are ready to test how columns are sorted...

I used following article as a base to my solution http://
69.10.233.10/KB/recipes/Sorting_with_Objects.aspx

Thursday, October 23, 2008

Biztalk 2006: Same Oracle view in multiple orchestrations

Problem

I want to use a same Oracle database view in multiple Biztalk orchestrations but Biztalk can't route messages correctly with a same pipeline even if port operation name is different for each orchestration.

Solution

Solution is simple. I had to add a new pipeline and own send port for each orchestration. Just remember to set an unique operation name for SOAP action header and select created pipeline for send/receive pipeline

Biztalk 2006: Oracle adapter namespace problem

Problem

I was deploying a Biztalk project from the development enviroment to the test enviroment when I encountered an error with Oracle adapter. That's because I have a different database schema name in both enviroments and database schema name is hard-coded to the schema.

This means that I can't use same SOAP header action in a send port for test and development enviroment and I didn't want to generate different schemas for different enviroments.

Solution

In a generated schema file I had namespaces with schema name on it:
http://Microsoft.LobServices.OracleDB/2007/03/NAMEOFSCHEMA/View/MYVIEWNAME

I removed schema name from the namespace:
http://Microsoft.LobServices.OracleDB/2007/03/View/MYVIEWNAME

Then I deployed project again. Next thing I did was changing the send port properties. Database schema name must be in SOAP header action even when schema name is not declared in a namespace

<BtsActionMapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Operation Name="portOperationName" Action="http://Microsoft.LobServices.OracleDB/2007/03/NAMEOFSCHEMA/View/MYVIEWNAME/Select" />
</BtsActionMapping>


I also changed couple of send port binding-properties EnableBiztalkCompabilityMode=true and useSchemaInNamespace=false.

Now I can deploy my Biztalk project to several enviroments without generating different schemas for each enviroment