创建table(如果不存在)并插入数据,无异常处理方式

create table (if not exist) and insert data without exception handling way

我正在使用 Npgsql version 4.1.3.1 作为 PostgreSQL 的 .NET 数据提供程序。这是我的用例

目前我正在使用 C# try/catch,在 try 中,我试图在 table 中插入记录,如果 table 不存在,那么在 catch I我正在尝试创建 table 并再次尝试重新插入。

private async Task<bool> Insert(Guid tableId, string name)
    {
        //here connection string is specific to table, which
        //don't have permission to create any table
        using (var conn = await GetTableConnectionString(tableId))
        {
            //open site specific connection
            await conn.OpenAsync();

            try
            {
                //insert data in table
                await using (var cmd = new NpgsqlCommand($@"Insert into Tbl-{tableId:N} (
                                                                id,
                                                                name) Values (@id, @name)", conn))
                {

                    cmd.Parameters.AddWithValue("id", Guid.NewGuid());
                    cmd.Parameters.AddWithValue("name", name);
                    await cmd.ExecuteNonQueryAsync();
                }

                //close site specific connection
                await conn.CloseAsync();
            }
            catch (Npgsql.PostgresException ex)
            {
                //close site specific connection
                await conn.CloseAsync();

                if (ex.SqlState == "42P01") // table does not exist
                {
                    //here admin connection string have permission to create a table
                    using (var adminConn = await GetAdminConnectionString())
                    {
                        try
                        {
                            //open admin specific connection
                            await adminConn.OpenAsync();

                            //create a table
                            using (var cmd = new NpgsqlCommand($@"CREATE Table Site_{tableId:N} (
                                                            id UUID PRIMARY KEY,
                                                            name VARCHAR(128);", adminConn))
                            {
                                cmd.ExecuteNonQuery();

                            }

                            //close admin specific connection
                            await adminConn.CloseAsync();

                            //insert data to table again
                            return await Insert(tableId, name);
                        }
                        catch (Exception exception)
                        {
                            //close admin specific connection
                            await adminConn.CloseAsync();
                            throw;
                        }
                    }
                }
            }
        }

        return true;
    }

问题是,

这种做法正确吗?无一例外地处理 (if (ex.SqlState == "42P01") // table does not exist) 我们是否有更好的方法或开箱即用的 ant 库在这里提供帮助? table 和管理员的连接字符串也不同。

鉴于您的具体设计,尝试捕获 42P01 似乎是合理的。另一种方法是首先检查 table 是否存在(通过查询 information_schema.tables 或 pg_class),但这增加了额外的往返并且可能容易受到竞争条件的影响。

但是,请考虑检查动态创建的 table 的设计。如果 table 具有相同的模式并且这里的目标是获得授权 per-table,那么 PostgreSQL 有 row-level security 这可能允许更好的设计。