创建table(如果不存在)并插入数据,无异常处理方式
create table (if not exist) and insert data without exception handling way
我正在使用 Npgsql version 4.1.3.1
作为 PostgreSQL 的 .NET 数据提供程序。这是我的用例
- 对于数据库,我必须动态创建 table,table 名称是
Guid
,我将其传递给一种方法。
- 如果存在特定的 table,则使用 table 特定的连接字符串(每个 table 都有自己的凭证),我需要插入数据放入 table.
- 如果 table 不存在则使用管理员连接字符串 (只有创建 table 的权限),我需要创建 table 然后在相应的 table.
中插入记录
目前我正在使用 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 这可能允许更好的设计。
我正在使用 Npgsql version 4.1.3.1
作为 PostgreSQL 的 .NET 数据提供程序。这是我的用例
- 对于数据库,我必须动态创建 table,table 名称是
Guid
,我将其传递给一种方法。 - 如果存在特定的 table,则使用 table 特定的连接字符串(每个 table 都有自己的凭证),我需要插入数据放入 table.
- 如果 table 不存在则使用管理员连接字符串 (只有创建 table 的权限),我需要创建 table 然后在相应的 table. 中插入记录
目前我正在使用 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 这可能允许更好的设计。