【问题标题】:SQL Compact Edition Batch UpdateSQL Compact Edition 批量更新
【发布时间】: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


【解决方案1】:

如果您的业务逻辑允许您“逐行”更新多个表中的数据(而不是使用复杂的 SQL 命令),您可以尝试“表直接”方法。它涉及以下步骤。

使用指向您的 SDF 文件的连接字符串创建 SqlCeConnection 对象。使用命令类型 CommandType.TableDirect 为该连接创建 SqlCeCommand 对象。使用选项 ResultSetOptions.UpdatableResultSetOptions.Scrollable 创建 SqlCeResultSet

现在您可以使用 SeekReadUpdate 方法更新表格行。这种方法可能是最快的方法。但与传统的 EF 方法相比,它需要编写更多的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多