Technical Insights: Azure, .NET, Dynamics 365 & EV Charging Architecture

Tag: .NET

Azure Service Bus Peek-Lock: A Comprehensive Guide to Reliable Message Processing

Working with Peek-Lock in Azure Service Bus: A Practical Guide

In many distributed systems, reliable message handling is a top priority. When I first started building an order processing application, I learned very quickly that losing even one message could cause major headaches. That’s exactly where Azure Service Bus and its Peek-Lock mode came to the rescue. By using Peek-Lock, you don’t remove the message from the queue as soon as you receive it. Instead, you lock it for a certain period, process it, and then decide what to do next—complete, abandon, dead-letter, or defer. Here’s how it all fits together.

Why Peek-Lock Matters

Peek-Lock is one of the two receiving modes offered by Azure Service Bus. The other is Receive and Delete, which automatically removes messages from the queue upon receipt. While that might be fine for scenarios where occasional message loss is acceptable, many real-world applications need stronger guarantees.

  1. Reliability: With Peek-Lock, if processing fails, you can abandon the message. This makes it visible again for another attempt, reducing the risk of data loss.
  2. Explicit Control: You decide when a message is removed. After you successfully handle the message (e.g., update a database or complete a transaction), you explicitly mark it as complete.
  3. Error Handling: If the same message repeatedly fails, you can dead-letter it for investigation. This helps avoid getting stuck in an endless processing loop.

What Happens If the Lock Expires?

By default, the lock is held for a certain period (often 30 seconds, which can be adjusted). If your code doesn’t complete or abandon the message before the lock expires, the message becomes visible to other receivers. To handle potentially lengthy processes, you can renew the lock programmatically, although that introduces additional complexity. The key takeaway is that you should design your service to either complete or abandon messages quickly, or renew the lock if more time is truly necessary.

Default Peek-Lock in Azure Functions

When you use Azure Service Bus triggers in Azure Functions, you generally don’t need to configure or manage the Peek-Lock behavior yourself. According to the official documentation, the default behavior in Azure Functions is already set to Peek-Lock. This means you can focus on your function’s core logic without explicitly dealing with message locking or completion in most scenarios.

Don’t Swallow Exceptions

One important detail to note is that in Azure Functions, any unhandled exceptions in your function code will signal to the runtime that message processing failed. This prevents the function from automatically completing the message, allowing the Service Bus to retry later. However, if you wrap your logic in a try/catch block and inadvertently swallow the exception—meaning you catch the error without rethrowing or handling it properly—you might unintentionally signal success. That would lead to the message being completed even though a downstream service might have failed.

Recommendation:

  • If you must use a try/catch, make sure errors are re-thrown or handled in a way that indicates failure if the message truly hasn’t been processed successfully. Otherwise, you’ll end up completing the message and losing valuable information about the error.

Typical Use Cases

  1. Financial Transactions: Losing a message that represents a monetary transaction is not an option. Peek-Lock ensures messages remain available until your code confirms it was successfully processed.
  2. Critical Notifications: If you have an alerting system that notifies users about important events, you don’t want those notifications disappearing in case of a crash.
  3. Order Processing: In ecommerce or supply chain scenarios, every order message has to be accounted for. Peek-Lock helps avoid partial or lost orders due to transient errors.

Example in C#

Here’s a short snippet that demonstrates how you can receive messages in Peek-Lock mode using the Azure.Messaging.ServiceBus library:

using System;
using System.Threading.Tasks;
using Azure.Messaging.ServiceBus;

public class PeekLockExample
{
    private const string ConnectionString = "<YOUR_SERVICE_BUS_CONNECTION_STRING>";
    private const string QueueName = "<YOUR_QUEUE_NAME>";

    public async Task RunPeekLockSample()
    {
        // Create a Service Bus client
        var client = new ServiceBusClient(ConnectionString);

        // Create a receiver in Peek-Lock mode
        var receiver = client.CreateReceiver(
            QueueName, 
            new ServiceBusReceiverOptions 
            { 
                ReceiveMode = ServiceBusReceiveMode.PeekLock 
            }
        );

        try
        {
            // Attempt to receive a single message
            ServiceBusReceivedMessage message = await receiver.ReceiveMessageAsync(TimeSpan.FromSeconds(10));

            if (message != null)
            {
                // Process the message
                string body = message.Body.ToString();
                Console.WriteLine($"Processing message: {body}");

                // If processing is successful, complete the message
                await receiver.CompleteMessageAsync(message);
                Console.WriteLine("Message completed and removed from the queue.");
            }
            else
            {
                Console.WriteLine("No messages were available to receive.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred: {ex.Message}");
            // Optionally handle or log the exception
        }
        finally
        {
            // Clean up resources
            await receiver.CloseAsync();
            await client.DisposeAsync();
        }
    }
}

What’s Happening Here?

  • We create a ServiceBusClient to connect to Azure Service Bus.
  • We specify ServiceBusReceiveMode.PeekLock when creating the receiver.
  • The code then attempts to receive one message and processes it.
  • If everything goes smoothly, we call CompleteMessageAsync to remove it from the queue. If something goes wrong, the message remains locked until the lock expires or until we choose to abandon it.

Final Thoughts

Peek-Lock strikes a balance between reliability and performance. It ensures you won’t lose critical data while giving you the flexibility to handle errors gracefully. Whether you’re dealing with financial operations, critical user notifications, or any scenario where each message must be processed correctly, Peek-Lock is an indispensable tool in your Azure Service Bus arsenal.

In Azure Functions, you get this benefit without having to manage the locking details, so long as you don’t accidentally swallow your exceptions. For other applications, adopting Peek-Lock might demand a bit more coding, but it’s well worth it if you need guaranteed, at-least-once message delivery.

Whether you’re building a simple queue-based workflow or a complex event-driven system, Peek-Lock ensures your messages remain safe until you decide they’re processed successfully. It’s a powerful approach that balances performance with reliability, which is why it’s a must-know feature for developers relying on Azure Service Bus.

Tag Replacement using Regex in .NET

This snippet of code shows how to do Synchronisation or HTML tag replacement

-My problem is i want to synchronise of tags between 2 HTML document

Issue

-Source.htm

my source.htm has this tag

<xml id=STATIC_CRITERIA_>

  <fields>

    <field fieldID=OPEN_FLAG displayType=checkboxGroup searchType=checkboxGroup underlyingType=int />

    <field fieldID=PARTITION displayType=dropdown searchType=profile profileID=SU_PARTITIONS underlyingType=int />

    <field fieldID=TEMPLATE_IND displayType=checkbox searchType=checkbox underlyingType=int />

    <field fieldID=INCLUDE_DELETED displayType=checkbox searchType=checkbox underlyingType=string />

  </fields>

</xml>

 -Target.htm has this tag

<xml id=STATIC_CRITERIA_>

</xml>

So now the problem is how do I fill the gap in XML tag in target.htm with the value from mySource.htm. We can do this using regex and it’s very simple

 

  string originalDocument = Load(“c:\\MySource.htm”);

                string syncDocument = Load(“c:\\Target.htm”);

 

                MatchCollection mc = Regex.Matches(originalDocument, “<xml([ ]?.*?)>(.*?)</xml>”, RegexOptions.Singleline | RegexOptions.IgnoreCase);

 

                foreach (Match m in mc)

                {

                    string token = “<xml{0}>”;

                    syncDocument = Regex.Replace(syncDocument, String.Format(token, m.Groups[1].Value) + “(.*?)</xml>”,

                                                               String.Format(token, m.Groups[1].Value) + m.Groups[2].Value + “</xml>”,

                                                               RegexOptions.Singleline | RegexOptions.IgnoreCase);

                }

 MatchCollection is used to return all the instances of that regular expression (e.g you might have multiple XML tags with different ID)

What does this tag means

“<xml([ ]?.*?)>(.*?)</xml>”

 ([ ]?.*) means that I don’t care whatever after it (e.g it can be ID or attributes etc). this is the first parameter that we stored on variable

(.*?) means that whatever inside the tag are captured into the second parameter that we stored on variable

You can access the first variable (e.g any attributes after the XML) by doing

m.Groups[1].Value

you can access the value inside the xml bracket by using

m.Groups[2].Value

so what  contains in

m.Groups[0].Value

it contains the whole xml tag that we extracted using regex

 then we can use regex.replace method to replace the tag in target html. When you replace the tag you need to replace the whole xml tag. You can’t just replace the inner part of it

   foreach (Match m in mc)

                {

                    string token = “<xml{0}>”;

                    syncDocument = Regex.Replace(syncDocument, String.Format(token, m.Groups[1].Value) + “(.*?)</xml>”,

                                                               String.Format(token, m.Groups[1].Value) + m.Groups[2].Value + “</xml>”,

                                                               RegexOptions.Singleline | RegexOptions.IgnoreCase);

                }

Send message in Twitter using .NET

This code snippet is used to wrap Twitter API to send message. It’s not a complete Twitter wrapper but It can send message using Twitter easily. There are two overloaded constructors where both of them requires user name and password to be passed and proxy server is used as the overloaded parameter.

using System;
using System.IO;
using System.Net;
using System.Xml;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Helpers
{
    public class TwitterHelpers
    {
        private string _twitterJsonUrl = "http://twitter.com/statuses/update.json";

        public string TwitterJsonUrl
        {
            get { return _twitterJsonUrl; }
            set { _twitterJsonUrl = value; }
        }

        private string _twitterUser = string.Empty;

        public string TwitterUser
        {
            get { return _twitterUser; }
            set { _twitterUser = value; }
        }

        private string _twitterPass = string.Empty;

        public string TwitterPass
        {
            get { return _twitterPass; }
            set { _twitterPass = value; }
        }

        private string _proxyServer = string.Empty;

        public string ProxyServer
        {
            get { return _proxyServer; }
            set { _proxyServer = value; }
        }

        public string SendTwitterMessage(string message)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(TwitterJsonUrl);
                System.Net.ServicePointManager.Expect100Continue = false;

                string post = string.Empty;
                using (TextWriter writer = new StringWriter())
                {
                    writer.Write("status={0}", HttpUtility.UrlEncode(message.Substring(0,140)));
                    post = writer.ToString();
                }

                SetRequestParams(request);

                request.Credentials = new NetworkCredential(TwitterUser, TwitterPass);

                using (Stream requestStream = request.GetRequestStream())
                {
                    using (StreamWriter writer = new StreamWriter(requestStream))
                    {
                        writer.Write(post);
                    }
                }

                WebResponse response = request.GetResponse();
                string content;

                using (Stream responseStream = response.GetResponseStream())
                {
                    using (StreamReader reader = new StreamReader(responseStream))
                    {
                        content = reader.ReadToEnd();
                    }
                }

                return content;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void SetRequestParams(HttpWebRequest request)
        {
            request.Timeout = 500000;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.UserAgent = "My Twitter Application";

            if (!string.IsNullOrEmpty(_proxyServer))
            {
                request.Proxy = new WebProxy(_proxyServer, false);
            }

        }

        public TwitterHelpers(string userName, string userPassword, string proxyServer)
        {
            _twitterUser = userName;
            _twitterPass = userPassword;
            _proxyServer = proxyServer;
        }

        public TwitterHelpers(string userName, string userPassword)
        {
            _twitterUser = userName;
            _twitterPass = userPassword;
        }

    }
}

Usage:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleAppTest
{
    class Program
    {
        private static TwitterHelpers _twitterHelpers = null;

        private static TwitterHelpers TwitterHelpers
        {
            get
            {
                if (_twitterHelpers == null)
                {
                    _twitterHelpers = new TwitterHelpers("twitteruser", "twitterpassword");
                }

                return _twitterHelpers;
            }
        }

        static void Main(string[] args)
        {
            TwitterHelpers.SendTwitterMessage("Hello World!!");
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
}

SQL Server Function using CLR

UPDATED: I’ve added one function to write from BLOB in SQL Server table to the disk straight away

I thought this article might be useful for anyone that wants to implement .NET code to SQL server level. In this case I really need CLR because I want to do compression of images and I believe it’s not possible to do that using pure SQL server stored procedure and I’m trying to avoid creating a .NET application just for compression of images through row by row processing.

Here we start:

This is your C#/.NET code, you need to declare it as SQL function or SQL stored procedure

using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using Zip = ICSharpCode.SharpZipLib.Zip.Compression;

namespace CLRCompressionFunctions
{
    public partial class CompressionCore
    {
        [SqlFunction()]
        public static SqlBytes fn_Compress(SqlBytes uncompressedBytes)
        {
            if (uncompressedBytes.IsNull)
                return uncompressedBytes;

            MemoryStream memory = new MemoryStream();

            ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream stream =
                new ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream(memory, new Zip.Deflater(Zip.Deflater.BEST_COMPRESSION), 131072);

            stream.Write(uncompressedBytes.Buffer, 0, Convert.ToInt32(uncompressedBytes.Length));
            stream.Flush();
            stream.Close();
            stream = null;

            return new SqlBytes(memory.ToArray());
        }

        [SqlFunction()]
        public static SqlBytes fn_Decompress(SqlBytes compressedBytes)
        {
            if (compressedBytes.IsNull)
                return compressedBytes;

            ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream stream =
                new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream(new MemoryStream(compressedBytes.Buffer));
            MemoryStream memory = new MemoryStream();
            byte[] writeData = new byte[4096];
            int size;

            while (true)
            {
                size = stream.Read(writeData, 0, writeData.Length);
                if (size > 0)
                {
                    memory.Write(writeData, 0, size);
                }
                else break;
            }
            stream.Flush();
            stream.Close();
            stream = null;

            return new SqlBytes(memory.ToArray());
        }

[SqlFunction()]
        public static SqlString fn_WriteFile(SqlString path, SqlBytes bytesFile, SqlBoolean isCompressed)
        {
            string returnString = string.Empty;

            try
            {
                //check if the file exists or not
                FileStream myFStream = new FileStream(path.ToString(), FileMode.OpenOrCreate, FileAccess.ReadWrite);

                SqlBytes fileBytes = bytesFile;

                if (isCompressed)
                {
                    fileBytes = fn_Decompress(bytesFile);
                }

                int Length = 256;
                Byte[] buffer = new Byte[Length];

                Stream readStream = fileBytes.Stream;

                int bytesRead = readStream.Read(buffer, 0, Length);

                // write the required bytes
                while (bytesRead > 0)
                {
                    myFStream.Write(buffer, 0, bytesRead);
                    bytesRead = readStream.Read(buffer, 0, Length);
                }

                readStream.Close();
                myFStream.Close();
                returnString = "File is written successfully";
            }
            catch (Exception ex)
            {
                returnString = ex.ToString();
            }

            return new SqlString(returnString);
        }
    }
}

Installation time to your SQL Server, You need to register your assembly(.dll) as well as referenced Assembly to SQL Server

ALTER DATABASE TestAssembly SET TRUSTWORTHY ON
GO
EXEC sp_configure 'clr enabled', 1;
RECONFIGURE WITH OVERRIDE;
GO
CREATE ASSEMBLY [ICSharpCode.SharpZipLib.dll]
                  FROM 'D:\Applications\FileCompressorApp\CLRCompressionFunctions\Deployment\ICSharpCode.SharpZipLib.dll'
                  WITH PERMISSION_SET = UNSAFE
GO
CREATE ASSEMBLY [CLRCompressionFunctions]
                  FROM 'D:\Applications\FileCompressorApp\CLRCompressionFunctions\Deployment\CLRCompressionFunctions.dll'
                  WITH PERMISSION_SET = EXTERNAL_ACCESS
GO

PERMISSION_SET = SAFE only if you don’t want the assembly accessing external resources such as writing to disk, but in this case the function is used to write into the disk
e.g How about if you want to use/register System.Drawing to your assembly? Yes you can do it by using

CREATE ASSEMBLY [System.Drawing.dll]
FROM 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll'
WITH PERMISSION_SET = UNSAFE

You need to enable the CLR on SQL server in order to use your function

Now you need to create your function based on your assembly

CREATE FUNCTION [fn_Compress]           (
                 @uncompressedBytes varbinary(MAX))
            RETURNS varbinary(MAX)
            AS    EXTERNAL NAME CLRCompressionFunctions.[CLRCompressionFunctions.CompressionCore].fn_Compress
GO
CREATE FUNCTION [fn_Decompress]           (
                 @uncompressedBytes varbinary(MAX))
            RETURNS varbinary(MAX)
            AS    EXTERNAL NAME CLRCompressionFunctions.[CLRCompressionFunctions.CompressionCore].fn_Decompress
GO
CREATE FUNCTION [fn_WriteFile]           (
                 @path nvarchar(4000),
				 @bytesFile varbinary(MAX),
				 @bitCompressed bit)
			RETURNS nvarchar(4000)
            AS    EXTERNAL NAME CLRCompressionFunctions.[CLRCompressionFunctions.CompressionCore].fn_WriteFile
GO

Usage, It’s the same as you call a function in SQL Server

SELECT dbo.[fn_Compress](testimage) FROM tblImages
SELECT dbo.[fn_Decompress](imgFileContent) FROM TABLE_NAME
GO
SELECT dbo.[fn_WriteFile]('c:\test.pdf',imgFileContent, 0) FROM TABLE_NAME
GO 

Linq.Binary(SQL Image Data Type) Type to File Stream

I got a column with Data Type of Image in SQL Server. What I would like to do is to omit this data to a FileStream or to a file. I tried to read the data using LINQ and I found the data type detected for that particular column is System.Data.Linq.Binary. I was expecting it to be Byte Data type. So I need to convert the Binary to byte then to File Stream. But I found a simpler way by using “ToArray” properties and cast it back to byte solves my problem.

    foreach (tblExpReceiptFile file in ExpReceiptFactory.tblExpReceiptFileSelect())
            {
                string fileName = file.vcFileName.Replace(" ","_");
                FileStream fileStream = File.Create(DirectoryPath + @"\" + fileName + ".pdf");
                fileStream.Write((byte[])file.imgFileContent.ToArray(), 0, ((byte[])file.imgFileContent.ToArray()).Length);
                fileStream.Close();
            }

Generic Logging Class in .NET

This is a snippet code which is useful in creating your own logging class. You can compile this as a library and use it accross the projects.

using System;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;

namespace MyLogging
{
    /// 
    /// provides event logging capabilities
    ///
    /// requires a LogSource setting in app/web.config, which must match the name of the event log
    /// 
    public class Logger
    {
        #region constants

        static readonly string ERROR_NOSOURCE = "MyLogging - cannot write to event log - please specify a LogSource in app/web.config";

        #endregion

        #region static ctor

        static Logger()
        {
            if (ConfigurationManager.AppSettings["LogSource"] == null)
            {
                throw new ApplicationException(ERROR_NOSOURCE);
            }
            else
            {
                _source = ConfigurationManager.AppSettings["LogSource"].ToString();

                if (!EventLog.SourceExists(_source))
                {
                    EventLog.CreateEventSource(_source, "Application");
                    EventLog.WriteEntry(_source, "log source created");
                }
            }
        }

        #endregion

        #region properties - LogSource

        private static string _source = null;

        public static string LogSource
        {
            get { return _source; }
            set { _source = value; }
        }

        #endregion

        #region public logging methods

        /// 
        /// logs an exception, using reflection to determine calling method and module
        /// 
        /// 
        public static void LogException(Exception ex)
        {
            MethodBase  method = ex.TargetSite;
            Module      module = method.Module;

            string      msg = module.Name + "." + method.Name
                            + " - " + ex.Message
                            + Environment.NewLine
                            + "Stack Trace - " + ex.StackTrace;

            LogMessage(msg, EventLogEntryType.Error);
        }

        /// 
        /// logs a (non-error) message
        /// 
        /// 
        public static void LogMessage(string message)
        {
            LogMessage(message, EventLogEntryType.Information);
        }

        /// 
        /// logs a message, with specified EventLogEntryType
        /// 
        /// 
        /// 
        private static void LogMessage(string message, EventLogEntryType type)
        {
            message = Assembly.GetExecutingAssembly().FullName + " - " + message;

            //if (_source == null)
            //{
            //    throw new ApplicationException(ERROR_NOSOURCE);
            //}

            EventLog.WriteEntry(_source, message, type);
        }

        #endregion
    }
}

webform_dopostbackwithoptions is undefined

A few days back I’ve got the error message “webform_dopostbackwithoptions is undefined” on the project that i’m working on.
The strange thing it happened only when I activated the securepagemodule, when i deactivated the module it works perfectly. I tried to debug it with HTTP debugger (fiddler tool) and i found that on that particular page, there is a request from webresources.axd but the request is not into https but into http and what i believe since the page is on secure mode therefore it discards the “webresources.axd” since it’s not secure. The workaround for this issue is by adding entry of “webresources.axd” under securepage and the problem is solved.

This is the sample of web.config for it

 
        
         
   </secureWebPages

NOTE:This is resolved in the new version of securepage module

Paging in Order BY using LINQ

This is a simple way of doing the paging in LINQ. If I do the paging before the ORDER BY then it will give me different result set. The paging is should be after the ORDER BY Statement. So you sort first then you paging it.

        /// 
        /// to get all the have your say using paging based on optional parameter
        /// of isapproved and sorted descending based on the posted date
        /// 
        /// 
        /// 
        /// 
        /// 
        public IQueryable HaveYourSaySelectApproved(bool? IsApproved, int startPage, int pageSize)
        {
            var haveyoursay = from h in HaveYourSayContext.HaveYourSays
                                      orderby h.DatePosted descending
			select h;

            if (IsApproved.HasValue)
            {
                haveyoursay = from h in HaveYourSayContext.HaveYourSays
                              where (h.IsApproved == IsApproved.Value)
                              orderby h.DatePosted descending
                              select h;
            }

	return haveyoursay.Skip(startPage * pageSize).Take(pageSize);
        }

Simple LINQ Tutorial

I’ve started learning about LINQ because I need to keep up to date with the latest technology out there. I’ve created a simple Business Layer which interact directly with Linq to SQL(DBML). It includes Insert, Update, Delete, Select and paging with LINQ.

Hopefully this tutorial will be useful enough for someone who is going to learn about LINQ. With LINQ we can really simplify/integrate the stored procedure into our Code base but it doesn’t mean LINQ does not support Stored Procedure.

It supports Stored Procedure as well since we might use Stored Procedure for complex calculation. You don’t need to create a table adapter anymore since LINQ does everything the same as table adapter.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LinqCore.Factories
{
    public class GroupFactory
    {

        /// 
        /// this is used to get all the groups
        /// 
        /// 
        public IQueryable GetAllGroups()
        {
            GroupsDataContext db = new GroupsDataContext();
            var groups = from g in db.Groups
                         select g;

            return groups;
        }

        /// 
        /// this is used to get the group based on the group id
        /// 
        /// 
        /// 
        public Group GetGroup(int groupid)
        {
            GroupsDataContext db = new GroupsDataContext();

            var groups = from g in db.Groups
                         where (g.GroupID == groupid)
                         select g;

            return groups.SingleOrDefault();
        }

        /// 
        /// this is used to insert Or Update which determined by the nullable
        /// integer value of the groupID
        /// 
        /// 
        /// 
        /// 
        public void GroupUpdate(int? groupID, string groupName, bool valid)
        {
            GroupsDataContext db = new GroupsDataContext();
            Group group = new Group();

            if (groupID.HasValue)
            {
               group = db.Groups.Single(p => p.GroupID == groupID.Value);
            }

            group.GroupName = groupName;
            group.valid = valid;

            if (!groupID.HasValue)
            {
                db.Groups.InsertOnSubmit(group);
            }
            db.SubmitChanges();
        }

        /// 
        /// this is used to delete a group based on its ID
        /// 
        /// 
        public void GroupDelete(int groupID)
        {
            GroupsDataContext db = new GroupsDataContext();

            Group group = db.Groups.Single(p => p.GroupID == groupID);
            db.Groups.DeleteOnSubmit(group);
            db.SubmitChanges();
        }

        /// 
        /// this is used to do paging for the returned result
        /// 
        /// 
        /// 
        /// 
        public IQueryable GetAllGroups(int startIndex, int pageSize)
        {
            GroupsDataContext db = new GroupsDataContext();
            var groups = from g in db.Groups
                         select g;

            return groups.Skip(startIndex).Take(pageSize);
        }
    }
}

COMException (0x80040154): Retrieving the COM class factory for component with CLSID

I’ve got this error when i tried to deploy my service with .NET wrapper for VB6 component :
System.Runtime.InteropServices.COMException (0x80040154): Retrieving the COM class factory for component with CLSID {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} failed due to the following error: 80040154
.

The workaround of this problem are:

  • Go to regedit and check for this entry {D8749532-0D3D-43B6-973C-C1D62BB6B3C7} ,(replace this with your clsid key) which is under “\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID”, If it is not exist then it almost certainly that you haven’t registered your VB6 component it self
  • Now you need to go to your project folder and find a reference folder and then copy the DLL that you created before (there will be several DLL under that folder, I believe you need to pick DLL with the largest size) and copy it to the same folder with your .NET DLL on production server
  • Register that DLL using “regsvr32 filename” (e.g regsvr32 APLCryptoCore.dll) and then restart your service and then it should be working
  • Powered by WordPress & Theme by Anders Norén