我正在尝试对 C# .NET 中的数据库进行批量“同步”(插入、更新和删除)。我使用 Dapper 是因为 Entity Framework 由于其他原因不适合该项目。有几个要求使我的问题变得格外困难:
Course
与 .NET DTO Course
匹配,其某些属性也作为列存在于数据库中。该解决方案目前如何运作:
repository.sync()
方法来“同步”单个客户的所有 DTO。Dictionary<Type, Dictionary<Synchronizable, TransactionType>>
的参数EntityToSync,其中
{Added, Updated, Deleted}
我正在努力解决的问题:
我觉得这很困难的原因是为了安全地生成SQL语句,需要使用参数。使用反射,我可以查看 DTO 具有的属性并生成语句。问题是实体的数量可能非常大,并且为每个项目使用唯一的参数可能会导致巨大的 DynamicParameter 对象。我相信 SQL Server 支持的参数数量是有限的。解决方案是分部分执行语句,但这是不可能的,因为同步应该是一个事务。
此外,为了防止解决方案使用大量资源,我希望生成尽可能少的语句和参数。我想我可以使用临时表来执行此操作,但我不确定如何操作,因为我还需要动态生成这些临时表并向其中插入内容,这可能与直接插入实际表完全相同。
TLDR;如何执行一个事务来批量插入、更新和删除数千条记录,以及如何从 .NET 类型的 PropertyInfo 生成执行此操作的代码?
我处理通用实体同步的方式是这样的:
为您的表创建一个镜像暂存表,即。课程 => 课程分期。 该表可以具有与目标相同的列,但可以为 NULL,以及一个标志列,该标志列说明如何处理实体、INSERT、UPDATE、DELETE
同步实体时,请找出它们属于哪个临时表,并使用 SQLBulkCopy 填充临时表。您仍然需要能够将属性映射到字段以及数据类型,但我猜您已经可以使用此代码。我猜您还可以使用 Dapper 来填充暂存表。这要简单得多,因为这里没有更新/删除,只有简单的插入
最后,您调用一些过程来构建一个 MERGE 语句,如下所示:
MERGE {TARGET} t
USING {SOURCE_STAGE} s
ON s.{ID} = t.{ID}
WHEN MATCHED AND s.flag = 'insert' THEN INSERT (
{COLUMNS}) VALUES({s.columns})
WHEN MATCHED AND s.flag = 'update' THEN UPDATE
SET {COLUMN_1} = s.{COLUMN_1}
...
WHEN MATCHED AND s.flag = 'delete' THEN DELETE
您需要动态生成内容,但这应该不会太难,您始终可以在 sys.columns 中查找列。
合并可以在显式事务中运行,最终你有一个完全更新的目标表