如何使用Dapper将(数组)批量插入到PostgreSQL中的两个相关表中?

时间:2017-09-06 13:00:17

标签: c# postgresql dapper npgsql

我试图将一批记录插入两个相关的表

例如。表格是

CREATE TABLE public.parent
(
  parent_id integer NOT NULL DEFAULT nextval('parent_id_seq'::regclass),
  name integer,
  CONSTRAINT parent_pkey PRIMARY KEY (parent_id)
);

CREATE TABLE public.child
(
  child_id integer NOT NULL DEFAULT nextval('child_id_seq'::regclass),
  parent_id integer,
  name integer,
  CONSTRAINT child_pkey PRIMARY KEY (child_id),
  CONSTRAINT child_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES public.parent (parent_id)
);

要插入一批parent及其children,我会执行以下操作 - 以下类映射到上表

public class parent 
{
    public int parent_id {get; set;}
    public string name {get; set;}
    public List<child> children {get; set;}
}

public class child 
{
    public int child_id {get; set;}
    public string name {get; set;}
    public int parent_id {get; set;}
}

为方便起见,我使用Dapper

var parents = new parent[] { ... }
var children = parents.SelectMany(p => p.children);

using (var connection = new NpgsqlConnection("..."))
{
    // map class to tables
    connection.MapComposite<parent>("public.parent");
    connection.MapComposite<child>("public.child");

    await connection.ExecuteAsync(@"
        insert into parent (name) 
        select 
            p.name
        from
            unnest(@parents) p;

        insert into child (parent_id, name) 
        select 
            c.parent_id,
            c.name
        from
            unnest(@children) c;
        ",
        new[] { 
            new NpgsqlParameter("parents", parents), 
            new NpgsqlParameter("children", children) 
        }, CommandType.Text);
}

显然,这不会起作用,因为parent_id不适用于第二批插入。有没有办法从第一个插入中获取插入的parent_id并将其与第二个插入一起使用,假设第二个使用参数化数组?或者是否有其他方法可以实现相同的结果,即批量插入相关数据?

注1:如果插入的值不是参数化数组https://dba.stackexchange.com/questions/89451/inserting-into-related-tables

,则可以使用数据修改CTE轻松完成此操作

注2:我能想到的另一种方法是预先填充代码中的主键(插入前),方法是使用select nextval('parent_id_seq') from generate_series(1, <number of parents inserting which we know beforehand>)之类的方式预先分配序列值,但这样做对我来说,这看起来不是正确的做法。

1 个答案:

答案 0 :(得分:1)

你的第二个音符 - “预先分配”序列值 - 这是一种非常合法的方式,有时也被称为hi-lo。实体框架核心提供程序将此行为作为标准功能支持。