【问题标题】:AWS Lambda Connect to Redshift DB using ODBC ConnectionAWS Lambda 使用 ODBC 连接连接到 Redshift DB
【发布时间】:2018-07-23 11:00:21
【问题描述】:

我正在尝试使用 .NEt Core 2.0 C# 应用程序中的 AWS Lambda 连接到 RedShift DB。

以下是我的方法。

string connString = "Driver={Amazon Redshift (x86)};" +
            String.Format("Server={0};Database={1};" +
            "UID={2};PWD={3};Port={4};SSL=true;Sslmode=Require",
            RedShiftServer, RedShiftDBName, RedShiftUsername,RedShiftPassword, RedShiftPort);
OdbcConnection conn = new OdbcConnection(connString);
conn.Open();

但在部署到 Lambda 函数后,我无法连接到 RedShift DB(无法打开连接)。

我收到波纹管错误。

"需要最低版本 2.3.1 的依赖 unixODBC。 无法加载 DLL 'libodbc.so.2':指定的模块或其之一 找不到依赖项。

好像是odbc的问题,怎么解决?

【问题讨论】:

标签: c# lambda odbc aws-lambda amazon-redshift


【解决方案1】:

我还尝试使用 ODBC 为我的 lambda 函数从 redshift 获取数据,但遇到问题“需要最低版本 2.3.1 的依赖 unixODBC”。

使用 Npgsql.EntityFrameworkCore.PostgreSQL 库代替使用 ODBC,如该线程中的 cmets 中所述。我正在尝试将其放在一起以提供帮助。这是我的代码,它从 redshift 读取 odbc 的连接字符串并将其与您的模型绑定,该模型在 redshift 中的表的类型和列名应该相同,而与大小写无关。

 public IEnumerable<T> ExcecuteSelectCommand<T>(string command, string connectionString)
    {
        var relevantConnectionString = GetConnectionStringWithoutDriver(connectionString);
        using (var conn = new NpgsqlConnection(relevantConnectionString))
        {
            try
            {
                conn.Open();
                using (var cmd = new NpgsqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.CommandText = command;
                    var reader = cmd.ExecuteReader();
                    return CreateList<T>(reader);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("There was exception while excecuting the Select Command for Detail, here is exception detail. " + ex.Message, ex);
            }
        }
    }

    private string GetConnectionStringWithoutDriver(string connection)
    {
        return connection.Replace("Driver={Amazon Redshift (x64)}; ", string.Empty);
    }


    private List<T> CreateList<T>(NpgsqlDataReader reader)
    {
        var results = new List<T>();
        Func<NpgsqlDataReader, T> readRow = this.GetReader<T>(reader);

        while (reader.Read())
        {
            try
            {
                var readData = readRow(reader);
                results.Add(readData);

            }
            catch
            {
                throw new Exception("Data mismatch exception has occured");
                //Log the information when data failed to load
            }

        }

        return results;
    }

    private Func<NpgsqlDataReader, T> GetReader<T>(NpgsqlDataReader reader)
    {
        Delegate resDelegate;

        List<string> readerColumns = new List<string>();
        for (int index = 0; index < reader.FieldCount; index++)
        {
            readerColumns.Add(reader.GetName(index));
        }

        // determine the information about the reader
        var readerParam = Expression.Parameter(typeof(NpgsqlDataReader), "reader");
        var readerGetValue = typeof(NpgsqlDataReader).GetMethod("GetValue");

        // create a Constant expression of DBNull.Value to compare values to in reader
        var dbNullValue = typeof(System.DBNull).GetField("Value");
        //var dbNullExp = Expression.Field(Expression.Parameter(typeof(System.DBNull), "System.DBNull"), dbNullValue);
        var dbNullExp = Expression.Field(expression: null, type: typeof(DBNull), fieldName: "Value");
        // loop through the properties and create MemberBinding expressions for each property
        List<MemberBinding> memberBindings = new List<MemberBinding>();
        foreach (var prop in typeof(T).GetProperties())
        {
            // determine the default value of the property
            object defaultValue = null;
            if (prop.PropertyType.IsValueType)
                defaultValue = Activator.CreateInstance(prop.PropertyType);
            else if (prop.PropertyType.Name.ToLower().Equals("string"))
                defaultValue = string.Empty;

            if (readerColumns.Contains(prop.Name.ToLower()))
            {
                // build the Call expression to retrieve the data value from the reader
                var indexExpression = Expression.Constant(reader.GetOrdinal(prop.Name.ToLower()));
                var getValueExp = Expression.Call(readerParam, readerGetValue, new Expression[] { indexExpression });

                // create the conditional expression to make sure the reader value != DBNull.Value
                var testExp = Expression.NotEqual(dbNullExp, getValueExp);
                var ifTrue = Expression.Convert(getValueExp, prop.PropertyType);
                var ifFalse = Expression.Convert(Expression.Constant(defaultValue), prop.PropertyType);

                // create the actual Bind expression to bind the value from the reader to the property value
                MemberInfo mi = typeof(T).GetMember(prop.Name)[0];
                MemberBinding mb = Expression.Bind(mi, Expression.Condition(testExp, ifTrue, ifFalse));
                memberBindings.Add(mb);
            }
        }

        // create a MemberInit expression for the item with the member bindings
        var newItem = Expression.New(typeof(T));
        var memberInit = Expression.MemberInit(newItem, memberBindings);


        var lambda = Expression.Lambda<Func<NpgsqlDataReader, T>>(memberInit, new ParameterExpression[] { readerParam });
        resDelegate = lambda.Compile();

        return (Func<NpgsqlDataReader, T>)resDelegate;
    }

【讨论】:

    【解决方案2】:

    当您在非 Windows 平台上使用 System.Data.Odbc 时,您必须安装 unixODBC(2.3.1 或更高版本)。然后,您需要安装所需的 ODBC 驱动程序(在您的情况下,这是 Amazon Redshift ODBC 驱动程序)并在 odbcinst.ini 中注册它。对于 AWS Lambda,您需要检查如何使用您的部署包部署 unixODBC 和 Redshift ODBC 驱动程序。

    【讨论】:

    • 嗨,Vitaliy,我也面临这个问题,你能帮我更详细地解决这个问题吗?因为我对此很陌生。
    • @shekharsingh 如果您需要从 .NET 连接到 Redshift,使用托管 NpgSql 驱动程序而不是 ODBC 可能更容易
    • 谢谢@Vitaliy 帮助。
    猜你喜欢
    • 2018-09-14
    • 2017-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 2018-02-26
    相关资源
    最近更新 更多