我有一个使用linq表达式的函数(ReturnStatementDetailsForSubRepAsync
),我可以使用.ToListAsync()
等构建函数轻松实现异步。现在因为这个LINQ函数是异步的,我必须使父函数异步。
父函数如下所示:
public async Task<IEnumerable<StatementDetail>> ReturnStatementDetailsAsync(string cid, string userName, int statementNo)
{
var statementDetails = new List<StatementDetail>;
if (HttpContext.Current.User.IsInRole(UserLevel.Subrep.GetDescription()) || HttpContext.Current.User.IsInRole(UserLevel.SubRepMaster.GetDescription()))
{
var subRepStmtDetails = await ReturnStatementDetailsForSubRepAsync(cid, userName, statementNo); //Linq query with ToListAsync()
foreach (var item in subRepStmtDetails)
{
statementDetails.Add(new SubRepStatementDetailItem(item));
}
}
else
{
var regionalStmtDetails = await Task.Run(() => StoredPrcedureAsyncTest(cid, statementNo); //Entity framework stored procedure call
foreach (var item in regionalStmtDetails)
{
statementDetails.Add(new RegionalStatementDetailItem(item));
}
}
return statementDetails;
}
StoredPrcedureAsyncTest
看起来像这样:
public async Task<IEnumerable<SelectStatementTransno_Result>> StoredPrcedureAsyncTest(string cid, int statementNo)
{
using (var dbContext = new WebDataEntities())
{
return await Task.Run(() => dbContext.SelectStatementTransno(cid, statementNo, Nothing).ToList());
}
}
现在我知道StoredPrcedureAsyncTest
执行IO工作所以我应该使它异步。那么我实现存储过程调用的方式是否会使我的方法完全异步,因为目前没有内置的实体框架解决方案来使存储过程调用异步?
答案 0 :(得分:1)
DbContext中的DbSets表示数据库中的表。 DbContext知道这些表之间的关系以及如何将LINQ查询转换为数据库理解的查询。 DbContext的任务是隐藏数据库的内部。只要您想与数据库通信,就可以使用DbContext。
因此,您的DbContext是放置存储过程的好地方。因为您的DbContext也创建模型(在DbContext.OnModelCreating中),它也是添加创建存储过程的功能的好地方。
DbContext的用户可能需要以下功能:
您的DbContext将使用DbContext.Database.ExecuteSqlCommand执行存储过程。此函数具有异步等效项:DbContext.Database.ExecuteSqlAsync
class MyDbContext : DbContext
{
// TODO: add DbSets
#region stored procedure
public void CallMyStoredProcedure(MyParams myParams)
{
object[] functionParameters = this.CreateFunctionParams(myParams);
this.Database.ExecuteSqlComment(sqlCommandMyStoredProcedure, functionParameters);
}
public async Task CallMyStoredProcedure(MyParams myParams)
{
object[] functionParameters = this.CreateFunctionParams(myParams);
await this.Database.ExecuteSqlCommentAsync(
sqlCommandMyStoredProcedure,
functionParameters)
.ConfigureAwait(false);;
}
// TODO: add more functions
#endregion stored procedures
}
这些功能使用其他几个功能:
// name of the stored procedure, names of the parameters:
private const string myStoredProcedureName = "InsertPoint";
private const string paramProductName = "ProductName";
private const string paramCount = "Count";
// SQL command to execute stored procedure with the parameters
private const string SqlCmndMyStoredProcedure = @"Exec "
+ myStoredProcedureName
+ @" @ParamProductName, @ParamCount";
private object[] CreateFunctionParams(MyParams myParams)
{
return newObject[]
{
new SqlParameter(paramProductName, myParams.ProductName),
new SqlParameter(paramCount, myParams.Count),
};
}
要使集合完成:添加一个方法来检查存储过程是否存在以及创建存储过程的方法:
检查存储过程是否已存在
public bool MyStoredProcedureExists()
{
return this.StoredProcedureExists(myStoredProcedureName);
}
public bool StoredProcedureExists(string procedureName)
{
object[] functionParameters = new object[]
{
new SqlParameter(@"procedurename", procedureName),
};
string query = @"select [name] from sys.procedures where name= @procedurename";
return this.Database.SqlQuery<string>(query, functionParameters)
.ToList()
.Where(item => item == procedureName)
.Any();
}
创建存储过程:
public void CreateMyStoredProcedure(bool forceCreate)
{
// do not create if already exists, except if forceCreate:
bool storedProcedureExists = this.MyStoredProcedureExists;
if (!storedProcedureExists || forceCreate)
{ // create the stored procedure:
var x = new StringBuilder();
// decide whether to create or Alter
if (!storedProcedureExists)
{
x.Append(@"CREATE");
}
else
{
x.Append(@"ALTER");
}
// procedure name:
x.Append(@" PROCEDURE ");
X.AppendLine(myStoredProcedureName);
// parameters:
x.AppendLine(@"@ProductName NVARCHAR(80),"
X.AppendLine(@"@Count int")
// procedure code:
x.AppendLine(@"AS")
X.AppendLine(@"BEGIN")
... // TODO: add procedure code
x.AppendLine(@"END");
this.Database.ExecuteSqlComment(x.ToString());
}
}
最后OnModelCreating:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
this.CreateMyStoredProcedure(false); // don't force if already exists;
// TODO: add fluent API
}