Dapper 多对多插入

Dapper many-to-many insert

第一次用Dapper,以前习惯直接写我的SQL

我有一个多对多关系的情况,所以我的 类 看起来像这样:

public class Product
{
    public int Id {get;set;}
    public string otherpropertiesremovedforbrevity Other {get;set;}
    ...
    public List<Attachment> Attachment {get;set;}
}


public class Attachment
{
    public int Id {get;set;}
    public string Name {get;set;}
    public string URL {get;set;}
}

在我的数据库中,我有一个 table 到 link 它们在一起,看起来像这样;

ProductId 
AttachmentId

(一个复合主键,并且都带有 Fk 到它们各自的 tables)。

但我不知道如何执行插入。下面是我的

  using (var connection = GetConnection)
  {
      connection.Open(); 
      using (var transaction = connection.BeginTransaction())
      {
          string pINSERT = "INSERT INTO prodcat.Product (otherpropertiesremovedforbrevity) " +
                " VALUES (@otherpropertiesremovedforbrevity) RETURNING Id;";

          string sql = "insert into prodcat.AttachmentProductSpecificationLink (ProductSpecificationId, AttachmentId) values(@Id, @AttachmentId)";


          var res = await connection.ExecuteScalarAsync(pINSERT, entity);    
          var arows = await connection.ExecuteAsync(aINSERT, entity.Attachment, transaction);

          transaction.Commit();
          return Convert.ToInt64(res);

      }
  }

但是我得到了错误

column "attachmentid" does not exist.

所以我显然没有以正确的方式处理这个问题。那么我需要做什么才能让它发挥作用?

Postgresql 是区分大小写的,你的列名是大写的,所以我想你应该在插入语句中引用列名:

string sql = "insert into prodcat.AttachmentProductSpecificationLink (\"ProductSpecificationId\", \"AttachmentId\") values(@Id, @AttachmentId)";

例如,如果您 运行 这个脚本:

CREATE TABLE _test("colName" integer);

SELECT * 
FROM _test 
WHERE colName = 1;

你会得到一个错误:

SQL Error [42703]: ERROR: column "colname" does not exist
Hint: Perhaps you meant to reference the column "_test.colName".
Position: 27

正确的方法是:


SELECT * 
FROM _test 
WHERE "colName" = 1;

我相信下面的代码片段对您有用。

您应该有 3 个插入语句,用于 Product、Attachment 和 AttachmentProductSpecificationLink。在您的示例代码中,您缺少一个。我假设您的 aINSERT 应该用于附件 table.

我注意到的另一件事是,你的 ExecuteScalarAsync returning 一个对象,所以我使用 ExecuteScalarAsync 来正确转换。

您的实体 (Product class) 变量包含附件列表,通常我会执行 ExecuteAsync 并传入列表,因为它是没有 returning 子句的普通插入。但是在您的情况下,您正在 returning ID,所以我选择使用 foreach 循环来迭代插入的附件。

在 foreach 循环中,我 return 将 returning ID 放入变量 attachmentId 并将其用于以下插入 AttachmentProductSpecificationLink 中。因为我们不是 return 任何东西,所以我执行 ExecuteAsync。

using (var connection = GetConnection())
            {
                connection.Open();
                using (var transaction = connection.BeginTransaction())
                {
                    string pINSERT = "INSERT INTO prodcat.Product (otherpropertiesremovedforbrevity) " +
                          " VALUES (@otherpropertiesremovedforbrevity) RETURNING Id;";

                    string aINSERT = "INSERT INTO prodcat.Attachment (Name, URL) " +
                          " VALUES (@Name, @Url) RETURNING Id;";

                    string sql = "insert into prodcat.AttachmentProductSpecificationLink (ProductSpecificationId, AttachmentId) values(@Id, @AttachmentId)";


                    var res = await connection.ExecuteScalarAsync<int>(pINSERT, entity, transaction);

                    foreach( var a in entity.Attachment)
                    {
                        var attachmentId = await connection.ExecuteScalarAsync<int>(aINSERT, a, transaction);

                        var arows = await connection.ExecuteAsync(sql, new { Id = res, AttachmentId = attachmentId }, transaction);
                    }

                    transaction.Commit();
                    return Convert.ToInt64(res);

                }
            }