I have a .NET Framework 4.6.1 WebAPI that exposes endpoints to perform CRUD operations. My client wants all operations performed in the context of an individual user account so I’m using SQL Server impersonation to make it work (all statements are written to an audit file so using SQL Impersonation allows us to see who is executing the statement). I get the username from the NameIdentifier claim and then execute statements using the “EXECUTE AS USER”
command.
An example to retrieve a single record via an ID is the following:
using (var transaction = SyncDbContext.Database.BeginTransaction())
{
await SyncDbContext.Database.ExecuteSqlCommandAsync($"EXECUTE AS USER = '{UserName}'");
var data = await LookupAsync(id);
await SyncDbContext.Database.ExecuteSqlCommandAsync("REVERT");
transaction.Commit();
return data;
}
The statements need to be performed inside a transaction otherwise SQL Server throws an exception. The audit file for this operation would contain the statements EXECUTE AS USER = [USERNAME],[Statement], REVERT
All CRUD operations work except for endpoints that return an IQueryable. I need to return an IQueryable to support the oData specification which allow the client to pass query string arguments to modify the query (e.g., a query string parameter containing $top=10 will become .Take(10) in the EF query).
The following is example of an endpoint that returns an IQueryable:
[EnableQuery(MaxTop = 1000)]
public async Task<IQueryable<Employee>> GetEmployees()
{
using (var transaction = SyncDbContext.Database.BeginTransaction())
{
await SyncDbContext.Database.ExecuteSqlCommandAsync($"EXECUTE AS USER = '{UserName}'");
var data = SyncDbContext.Employees.AsQueryable();
await SyncDbContext.Database.ExecuteSqlCommandAsync("REVERT");
transaction.Commit();
return data;
}
}
The problem is that due to the deferred execution of iQueryable the audit file contains the statements out of order - EXECUTE AS USER = [USERNAME], [REVERT], [STATEMENT]. Is there a way to make the IQueryable statement “execute" with the transaction or a better way of achieving my goal?
question from:
https://stackoverflow.com/questions/65846504/returning-iqueryable-from-web-api-methods-using-sql-server-impersonation 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…