我有2个表ClassMaterial和ClassSubMatRelation。
ClassMaterial
[ClassMaterialID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[Description] [nvarchar](1000) NULL,
[EbookLink] [nvarchar](500) NULL,
[Status_Info] [smallint] NULL DEFAULT ('1'),
[SEOTitle] [nvarchar](100) NULL,
[SEOKeyword] [nvarchar](50) NULL,
[SEODesc] [nvarchar](500) NULL
ClassSubMatRelation
[ClassSubMatRelationID] [int] IDENTITY(1,1) NOT NULL,
[BoardFK] [int] NULL,
[ClassFK] [int] NULL,
[ClassSubjectFK] [int] NOT NULL,
[MaterialTypeFK] [int] NOT NULL,
[ClassMaterialFK] [int] NOT NULL,
[Status_Info] [smallint] NOT NULL
我将ClassMaterial c#中的多条记录保存为: -
foreach (var eachMaterial in value.materialModel)
{
DataRow dr = dt.NewRow();
dr[Constants.Name] = eachMaterial.Heading;
dr[Constants.Description] = eachMaterial.Descr;
dr[Constants.EbookLink] = eachMaterial.Ebook;
dr[Constants.SEODesc] = eachMaterial.SEODesc;
dr[Constants.SEOTitle] = eachMaterial.SEOTitle;
dr[Constants.SEOKeyword] = eachMaterial.SEOKeyword;
dt.Rows.Add(dr);
}
using (SqlBulkCopy SQLbulk = new SqlBulkCopy(sqlcon))
{
SQLbulk.ColumnMappings.Add(Constants.Name, Constants.Name);
SQLbulk.ColumnMappings.Add(Constants.Description, Constants.Description);
SQLbulk.ColumnMappings.Add(Constants.EbookLink, Constants.EbookLink);
SQLbulk.ColumnMappings.Add(Constants.SEODesc, Constants.SEODesc);
SQLbulk.ColumnMappings.Add(Constants.SEOTitle, Constants.SEOTitle);
SQLbulk.ColumnMappings.Add(Constants.SEOKeyword, Constants.SEOKeyword);
SQLbulk.DestinationTableName = value.aBundleInsert.MainTblName;
SQLbulk.WriteToServer(dt);
}
我的问题是在ClassSubMatRelation中我有ClassMaterialFK列,它是ClassMaterial中ClassMaterialID列的外键。所以我想将ClassMaterial中插入的所有新记录的ClassMaterialIDs与其他记录一起保存到ClassSubMatRelation中。 我经历过this ques。它建议使用OUTPUT子句,但它需要大量的代码更改。我也无法理解this ques。有没有其他方法这样做?提前谢谢。
修改
所以在@Zohar的帮助下,我实现了我想要的目标: -
CREATE TYPE udt_classMaterial_base As Table
(
classMaterial_id int,
base_classMaterial_temp_id int,
[Name] [nvarchar](100) NOT NULL,
[Description] [nvarchar](1000) NULL,
[EbookLink] [nvarchar](500) NULL,
[Status_Info] [smallint] NULL DEFAULT ('1'),
[SEOTitle] [nvarchar](100) NULL,
[SEOKeyword] [nvarchar](50) NULL,
[SEODesc] [nvarchar](500) NULL
);
CREATE TYPE udt_classSubMatRel_related As Table
(
related_classSubMatRel_base_id int,
[BoardFK] [int] NULL,
[ClassFK] [int] NULL,
[ClassSubjectFK] [int] NOT NULL,
[MaterialTypeFK] [int] NOT NULL,
[ClassMaterialFK] [int] NOT NULL,
[Status_Info] [smallint] NOT NULL
);
CREATE TYPE udt_classMaterial_idMap as table
(
temp_id int,
id int
)
GO
我的程序如下: -
ALter PROCEDURE stp_InsertMultipleRecordsToMultipleTables
(
@base as dbo.udt_classMaterial_base readonly,
@related as dbo.udt_classSubMatRel_related readonly,
@ReturnBool int out
)
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
DECLARE @idMap as dbo.udt_classMaterial_idMap
MERGE INTO ClassMaterial USING @base AS temp ON 1 = 0 -- Always not matched
WHEN NOT MATCHED THEN
INSERT (Name,Description,EbookLink,SEOTitle,SEOKeyword,SEODesc)
VALUES (temp.Name,temp.Description,temp.EbookLink,temp.SEOTitle,temp.SEOKeyword,temp.SEODesc)
OUTPUT temp.base_classMaterial_temp_id, inserted.ClassMaterialID -- Here we use the base_temp_id to map to the correct id
INTO @idMap (temp_id, id);
INSERT INTO ClassSubMatRelation(BoardFK, ClassFK,ClassMaterialFK,ClassSubjectFK,MaterialTypeFK)
SELECT BoardFK, ClassFK, id, ClassSubjectFK,MaterialTypeFK
FROM @related r
INNER JOIN @idMap m ON(r.related_classSubMatRel_base_id = m.temp_id) -- here we use the map to insert the related records with the correct base ids
SET @ReturnBool = 1;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF (XACT_STATE()) = -1
BEGIN
SET @ReturnBool = 0;
ROLLBACK TRANSACTION;
END;
IF (XACT_STATE()) = 1
BEGIN
COMMIT TRANSACTION;
END;
END CATCH
Return @ReturnBool
END GO
和C#方法: -
public int BulkInsertBoard(RequestData value)
{
int ReturnBool = 0;
try
{
DataTable dtRel = new DataTable();
dtRel.Columns.Add("related_classSubMatRel_base_id");
dtRel.Columns.Add("BoardFK");
dtRel.Columns.Add("ClassFK");
dtRel.Columns.Add("ClassSubjectFK");
dtRel.Columns.Add("MaterialTypeFK");
dtRel.Columns.Add("ClassMaterialFK");
dtRel.Columns.Add(Constants.StatusInfo);
DataTable dt = new DataTable();
dt.Columns.Add("classMaterial_id");
dt.Columns.Add("base_classMaterial_temp_id");
dt.Columns.Add(Constants.Name);
dt.Columns.Add(Constants.Description);
dt.Columns.Add(Constants.EbookLink);
dt.Columns.Add(Constants.StatusInfo);
dt.Columns.Add(Constants.SEOTitle);
dt.Columns.Add(Constants.SEOKeyword);
dt.Columns.Add(Constants.SEODesc);
using (var sqlcon = new SqlConnection(Constants.Connection))
{
SqlDataAdapter adapter = new SqlDataAdapter("DECLARE @udt_classMaterial_base dbo.udt_classMaterial_base SELECT * FROM @udt_classMaterial_base", sqlcon);
adapter.FillSchema(dt, SchemaType.Source);
foreach (var eachMaterial in value.materialModel)
{
DataRow dr = dt.NewRow();
if (dt.Columns.Contains("classMaterial_id") && dt.Columns["classMaterial_id"].DataType == typeof(int))
dr["classMaterial_id"] = 0;
if (dt.Columns.Contains("base_classMaterial_temp_id"))
dr["base_classMaterial_temp_id"] = 0;
dr[Constants.Name] = eachMaterial.Heading;
dr[Constants.Description] = eachMaterial.Descr;
if (dt.Columns.Contains(Constants.EbookLink) && dt.Columns[Constants.EbookLink].DataType == typeof(string))
dr[Constants.EbookLink] = eachMaterial.Ebook;
dr[Constants.StatusInfo] = Convert.ToInt16(1);
if (!string.IsNullOrEmpty(eachMaterial.SEODesc))
dr[Constants.SEODesc] = eachMaterial.SEODesc;
if (!string.IsNullOrEmpty(eachMaterial.SEOTitle))
dr[Constants.SEOTitle] = eachMaterial.SEOTitle;
if (!string.IsNullOrEmpty(eachMaterial.SEOKeyword))
dr[Constants.SEOKeyword] = eachMaterial.SEOKeyword;
dt.Rows.Add(dr);
}
SqlDataAdapter adapterRel = new SqlDataAdapter("DECLARE @udt_classSubMatRel_related dbo.udt_classSubMatRel_related SELECT * FROM @udt_classSubMatRel_related", sqlcon);
adapterRel.FillSchema(dtRel, SchemaType.Source);
DataRow drRel = dtRel.NewRow();
if (dtRel.Columns.Contains("related_classSubMatRel_base_id"))
drRel["related_classSubMatRel_base_id"] = 0;
drRel["BoardFK"] = value.aBundleInsert.BoardFK;
drRel["ClassFK"] = value.aBundleInsert.ClassesFK;
drRel["ClassSubjectFK"] = value.aBundleInsert.ClassSubjectFK;
drRel["MaterialTypeFK"] = value.aBundleInsert.MaterialIndicator;
if (dtRel.Columns.Contains("ClassMaterialFK"))
drRel["ClassMaterialFK"] = value.aBundleInsert.MaterialFetchID;
drRel[Constants.StatusInfo] = Convert.ToInt16(1);
dtRel.Rows.Add(drRel);
using (SqlCommand cmd = new SqlCommand(Constants.ProcNameBulkInsertBoard))
{
cmd.Connection = sqlcon;
cmd.CommandType = CommandType.StoredProcedure;
if (sqlcon.State == System.Data.ConnectionState.Closed)
{
sqlcon.Open();
}
cmd.Parameters.AddWithValue("@base", dt);
cmd.Parameters.AddWithValue("@related", dtRel);
SqlParameter outputParam = new SqlParameter();
outputParam.ParameterName = "@ReturnBool";
outputParam.SqlDbType = System.Data.SqlDbType.Int;
outputParam.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.Add(outputParam);
cmd.ExecuteNonQuery();
if (!cmd.Parameters["@ReturnBool"].Value.Equals(DBNull.Value))
{
ReturnBool = Convert.ToInt32(cmd.Parameters["@ReturnBool"].Value);
}
}
}
//using (SqlBulkCopy SQLbulk = new SqlBulkCopy(sqlcon))
//{
// SQLbulk.ColumnMappings.Add(Constants.Name, Constants.Name);
// SQLbulk.ColumnMappings.Add(Constants.Description, Constants.Description);
// SQLbulk.ColumnMappings.Add(Constants.EbookLink, Constants.EbookLink);
// SQLbulk.ColumnMappings.Add(Constants.SEODesc, Constants.SEODesc);
// SQLbulk.ColumnMappings.Add(Constants.SEOTitle, Constants.SEOTitle);
// SQLbulk.ColumnMappings.Add(Constants.SEOKeyword, Constants.SEOKeyword);
// SQLbulk.DestinationTableName = value.aBundleInsert.MainTblName;
// SQLbulk.WriteToServer(dt);
//}
}
catch (Exception ex)
{
string error = ex.Message;
return ReturnBool;
//return new JsonResult { Data = ex.Message, JsonRequestBehavior=JsonRequestBehavior.AllowGet };
}
return ReturnBool;
}
希望这能帮助有需要的人。