获取输出'插入'使用Entity Framework进行更新

时间:2018-04-16 13:05:23

标签: c# entity-framework tsql entity-framework-6

SQL Server为插入和更新的记录提供输出'插入'关键字。

我有一个表示处理队列的表。我使用以下查询来锁定记录并获取锁定记录的ID:

UPDATE TOP (1) GlobalTrans
SET LockDateTime = GETUTCDATE()
OUTPUT inserted.ID
WHERE LockDateTime IS NULL

这将输出一个名为ID的列,其中包含所有更新的记录ID(在我的情况下是一个ID)。如何在C#中将其转换为EF以执行更新并获取ID?

2 个答案:

答案 0 :(得分:1)

实体框架无法做到这一点。

您可以通过选择所有记录,设置其LockDateTime并将其写回来以ORM方式执行此操作。这可能对你想做的事情不安全,因为默认情况下它不是单一的交易。

您可以跨越自己的交易并使用RepeatableRead作为隔离级别。这应该工作。根据您的数据库在后台执行的操作,它可能有点过分。

您可以编写SQL by hand。这违背了实体框架的目的,但就锁定机制而言,它应该像以前一样安全。

您也可以将其放入存储过程and call that。它比上面的版本好一点,因为至少某人会编译它并检查表名和列名是否正确。

答案 1 :(得分:1)

简单示例#1获取数据表:

我直接针对连接执行此操作: 将command.ExecuteNonQuery()更改为command.ExecuteReader()

        var connection = DbContext().Database.Connection as SqlConnection;

        using (var command = connection.CreateCommand())
        {
            command.CommandText = sql;
            command.CommandTimeout = 120;
            command.Parameters.Add(param);

            using (var reader = command.ExecuteReader())
            {
                var resultTable = new DataTable();
                resultTable.Load(reader);
                return resultTable;
            }
        }

仅供参考,如果您的SQL中没有OUTPUT子句,它将返回一个空的数据表。

返回实体的示例#2:

这有点复杂,但确实可行。 使用插入了OUTPUT的SQL语句。*

         var className = typeof(T).Name;
         var container = ObjContext().MetadataWorkspace.GetEntityContainer(UnitOfWork.ObjContext().DefaultContainerName, DataSpace.CSpace);
         var setName = (from meta in container.BaseEntitySets where meta.ElementType.Name == className select meta.Name).First();

         var results = ObjContext().ExecuteStoreQuery<T>(sql, setName, trackingEnabled ? MergeOption.AppendOnly : MergeOption.NoTracking).ToList();

T是正在处理的实体