我目前正在使用Entity Framework,需要定期更新大量实体。
我需要做的是添加一个基于几个不同表的日记编号。使用SQL Server,我可以使用存储过程,内部和外部联接,GROUP BY和ROW_NUMBER,这对我来说非常重要,也非常有效。
请参阅以下过程代码:
CREATE PROCEDURE [dbo].[sp_UpdateNumber]
@RefId int
AS
BEGIN
UPDATE TableWithNumber
SET Nmr = other.Nmr
FROM (
SELECT MIN(C.Nmr) as Nmr, Z_ID
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY D.TicksCreatedOn, D.Z_Id, D.B_ID) as Nmr, D.*
FROM (
SELECT
S.Id as S_ID,
Z.Id as Z_ID,
B.Id as B_ID,
S.TicksCreatedOn
FROM
ChildTable as B
INNER JOIN TableWithNumber Z on Z.ChildTableRefA_Id = B.Id
INNER JOIN ParentTable S on Z.ParentTable_Id = S.Id
WHERE S.Ref_Id = @RefId
UNION
SELECT
S.Id as S_ID,
Z.Id as Z_ID,
B.Id as B_ID,
S.TicksCreatedOn
FROM
ChildTable as B
INNER JOIN TableWithNumber Z on Z.ChildTableRefB_Id = B.Id
INNER JOIN ParentTable S on Z.ParentTable_Id = S.Id
WHERE S.Ref_Id = @RefId) as D
) as C
GROUP BY C.Z_ID) as other
WHERE other.Z_ID = Id AND Ref_Id = @RefId
END
由于SQL Ce中没有可用的存储过程,以及如何在子选择中使用GROUP BY的进一步限制,我现在必须计算代码中的日记数。我在Context上使用SqlQuery来检索所需的最小数据集,对其进行分组,然后开始每个实体的更新。
SELECT ZID
FROM
(SELECT S.Id as [SID], Z.Id as [ZID], B.Id as [BID], S.TicksCreatedOn
FROM ChildTable AS B
INNER JOIN TableWithNumber as Z on Z.ChildTableRefA_Id = B.Id
INNER JOIN ParentTable as S on Z.ParentTable_Id = S.Id
WHERE S.Ref_Id = @RefId
UNION
SELECT S.Id as [SID], Z.Id as [ZID], B.Id as [BID], S.TicksCreatedOn
FROM ChildTable AS B
INNER JOIN TableWithNumber as Z on Z.ChildTableRefB_Id = B.Id
INNER JOIN ParentTable as S on Z.ParentTable_Id = S.Id
WHERE S.Ref_Id = @RefId) AS D
ORDER BY TicksCreatedOn, ZID, BID
var result = Database.SqlQuery<NumberUpdate>(QUERY, new SqlCeParameter("@RefId", 1)).ToList();
应用程序上的代码看起来有点像
var grouped = result
.Select((x,y) => new NumberUpdate { ZID = x.ZID, Number = ++y })
.GroupBy(x => x.ZID);
foreach (var group in grouped)
{
Database.ExecuteSqlCommand("UPDATE TableWithNumber SET Number = @Nr WHERE Id = @Id",
new SqlCeParameter("@Nr", group.Min(x => x.Number)),
new SqlCeParameter("@Id", group.Key));
}
我想知道在SQL CE中更新实体列表是否比在foreach循环中调用ExecuteSqlCommand更快或更有效?
答案 0 :(得分:0)
如果您的业务逻辑允许您“逐行”更新多个表中的数据(不是使用复杂的SQL命令),您可以尝试“表直接”方法。它涉及以下步骤。
使用指向SDF文件的连接字符串创建 SqlCeConnection 对象。使用命令类型 CommandType.TableDirect 为此连接创建 SqlCeCommand 对象。使用选项 ResultSetOptions.Updatable 和 ResultSetOptions.Scrollable 创建 SqlCeResultSet 。
现在,您可以使用 Seek , Read 和 Update 方法更新表行。这种方法可能是最快的方法。但它需要编写比传统EF方法更多的代码。