Search code examples
c#asp.net.netasp.net-core

.NET Firebird client connection error, System.BadImageFormatException


I keep catching the following exception when trying to open a Firebird SQL connection. I suspect there may be an issue with the connection string I have supplied.

System.BadImageFormatException: 'An attempt was made to load a program with an incorrect format. (0x8007000B)'

This exception was originally thrown at this call stack:
    [External Code]
    KPS_DSR_Updater.DAL.CreateConnecton(FirebirdSql.Data.FirebirdClient.FbConnectionStringBuilder) in DAL.cs

Here is the code I've written:

using FirebirdSql.Data.FirebirdClient;
using Microsoft.Extensions.Configuration;
using System.Data;

namespace KPS_DSR_Updater
{
    internal class DAL : IDisposable
    {
        public FbConnectionStringBuilder? _connectionStringBuilder;
        private string? _connectionString;
        private FbConnection? _connection;
        private IConfiguration _configuration;

        public DAL(IConfiguration configuration)
        {
            // Initialize configuration and check for null value.
            _configuration = configuration ??
                throw new ArgumentNullException(nameof(configuration));

            try
            {
                List<string> parsedConnectionInfo = ParseConfiguration(_configuration);

                // Build the connection string using the parsed configuration
                // file containing connection info.
                _connectionStringBuilder = new FbConnectionStringBuilder
                {
                    ClientLibrary = parsedConnectionInfo[0],
                    Database = parsedConnectionInfo[1],
                    UserID = parsedConnectionInfo[3],
                    Password = parsedConnectionInfo[2],
                    ServerType = FbServerType.Embedded
                };
            }
            catch (Exception ex)
            {
                // Error re-thrown for Event Log. Outputting to console for
                // debugging purposes only.
                Console.WriteLine($"Error occured attempting to build connection string\n" +
                    $"{ex.Message}");
                throw;
            }
        }

        public void CreateConnecton(FbConnectionStringBuilder connectionStringBuilder)
        {
            // Build connection string and open connection. Connection string must first be
            // converted to a string, from FbConnectionStringBuilder object.
            try
            {
                // Convert to string
                _connectionString = connectionStringBuilder.ToString();
                _connection = new FbConnection(_connectionString);
                _connection.Open();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error occured attempting to make connection to database.\n" +
                    $"{ex.Message}");
                throw;
            }
        }

        private List<string> ParseConfiguration(IConfiguration configuration)
        {
            // Grab configuration settings from appsettings.json, if not null.
            List<string> configurationInfo = configuration.GetSection("connection_info").Get<List<string>>() 
                ?? throw new NoNullAllowedException();

            return configurationInfo;
        }

        public void Dispose()
        {
            // If necessary, close connection at program end of lifetime.
            if (_connection != null) _connection.Close();
        }
    }
}

And here is how I'm calling it:

using FirebirdSql.Data.FirebirdClient;
using KPS_DSR_Updater;
using Microsoft.Extensions.Configuration;


// Build config from configuration file.
var configurationBuilder = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
var configuration = configurationBuilder.Build();

// Create a new DAL object and apply connection_settings from configuration.
DAL DataAccessLayer = new DAL(configuration);

// Open connection to database.
FbConnectionStringBuilder connectionStringBuilder = DataAccessLayer._connectionStringBuilder!;
DataAccessLayer.CreateConnecton(connectionStringBuilder);

I have tried to hard code the connection string and make the same call, but it is still producing the same error. Interestingly, I'm referring to some work another developer has done that currently works and is in production, and I have followed the same conventions, so I'm not sure why this won't work in the same way.

For reference, here is the connection string with confidential information removed:

client library=fbclient.dll;initial catalog=DATA.FDB;user id=example;password=example;server type=Embedded

SOLUTION: The solution was quite simple. I just had to download a 64-bit binary from Firebird for the ODBC driver. That was then usable as my program is 64-bit, so the binary needs to match!


Solution

  • A System.BadImageFormatException error is very often an indication of a mismatched platform/bitness - for example, a 64-bit application trying to load a 32-bit DLL.

    The Firebird ODBC drivers are platform-specific:

    • For 64-bit applications, download a driver with name ending in "-x64".
    • For 32-bit applications, download a driver with name ending in "-Win32".

    As noted by the asker, replacing the driver with one whose bitness matched that of the application resolved the problem in this case.