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);
}
}
第一次用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);
}
}