我们的方法(使用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