SQL Server为插入和更新的记录提供输出'插入'关键字。
我有一个表示处理队列的表。我使用以下查询来锁定记录并获取锁定记录的ID:
UPDATE TOP (1) GlobalTrans
SET LockDateTime = GETUTCDATE()
OUTPUT inserted.ID
WHERE LockDateTime IS NULL
这将输出一个名为ID的列,其中包含所有更新的记录ID(在我的情况下是一个ID)。如何在C#中将其转换为EF以执行更新并获取ID?
答案 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是正在处理的实体