我們的方法(使用SQL Server 2008 R2)是將表值參數(TVP)與合併語句結合使用。
這種方式代碼將項目列表作爲表格傳遞給存儲過程。 proc然後在插入/更新/刪除的合併語句中使用該表。
你需要一個用戶定義的表類型,例如:
CREATE TYPE [dbo].[Participants] AS TABLE(
[ProjectId] [int] NOT NULL,
[ParticipantId] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[ProjectId] ASC,
[ParticipantId] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)
GO
然後你需要一個C#類來保存數據。只需修改IdCollection
是相似的:
public class IdCollection : List<ParticipantUsers>, IEnumerable<SqlDataRecord> {
#region IEnumerable<SqlDataRecord> Members
IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator() {
SqlDataRecord rec = new SqlDataRecord(
new SqlMetaData("ProjectId", System.Data.SqlDbType.Int),
new SqlMetaData("ParticipantId", System.Data.SqlDbType.Int)
);
foreach (ParticipantUser ans in this) {
rec.SetInt32(0, ans.ProjectId);
rec.SetInt32(1, ans.ParticipantId);
yield return rec;
}
}
#endregion
}
你的存儲過程將是這個樣子:
CREATE PROCEDURE [dbo].[ParticpantUpdate]
@Particpants core.Participants READONLY
AS
BEGIN
SET NOCOUNT ON;
MERGE INTO dbo.ProjectParticipants pp
USING @Particpants RG
ON (RG.ProjectId = pp.ProjectId)
AND (RG.ParticipantId = pp.ParticipantId)
WHEN NOT MATCHED BY TARGET THEN
INSERT(ProjectId, ParticipantId)
VALUES(RG.ProjectId, RG.ParticipantId)
WHEN NOT MATCHED BY SOURCE
AND target.ProjectId in (SELECT ProjectId from @Participants) THEN
DELETE;
;
END
要調用PROC(使用企業庫):
SqlDatabase db = DatabaseFactory.CreateDatabase("myconnstr") as SqlDatabase;
using (DbCommand dbCommand = db.GetStoredProcCommand("dbo.ParticipantUpdate")) {
db.AddInParameter(dbCommand, "Participants", SqlDbType.Structured, participantList);
db.ExecuteNonQuery(dbCommand);
} // using dbCommand
因爲它沒有被標記爲這樣,我猜你的倉庫沒有使用任何種類的ORM(EF/NHibernate)? –
從數據庫中獲取當前列表。與'ParticipantUsers'比較。如果缺少則添加,如果不再在「ParticipantUsers」中移除,則不要觸摸 – musefan
@SimonBelanger:正確,無ORM。我會爲我的OP添加一個說明。 – CesarGon