【发布时间】:2014-10-29 14:32:22
【问题描述】:
我目前正在使用实体框架,需要定期更新大量实体。
我需要做的是添加一个基于几个不同表的日记帐编号。使用 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));
}
我想知道是否有比在 foreach 循环中调用 ExecuteSqlCommand 更快或更有效的方法来更新 SQL CE 中的实体列表?
【问题讨论】:
-
我能找到的唯一改进是在
foreach循环之前准备 SqlCeCommand,然后在循环内只更改现有参数的值。但是 UPDATE 在 SQL CE 中非常有限。 -
如果您需要在可嵌入数据库中存储过程和触发器,请考虑LocalDB。
-
LocalDB 会很棒并且会喜欢使用它。但是,我们的应用程序的一个关键要求是,它应该是可部署的副本/过去,并且不需要安装例程。由于 LocalDB 需要在客户端上进行设置,不幸的是它不是一个选项。再一次,我很想使用它。
标签: sql sql-server-ce entity-framework-6