我正在开发一个asp.net mvc5 Web应用程序+实体框架6.我希望在我的应用程序中有一个存储库模型类。目前我正在遵循这种方法来拥有异步操作方法和异步存储库模型类。
例如,我有以下存储库保存方法: -
public class Repository
{
private Entities t = newEntities();
public async Task Save()
{
await t.SaveChangesAsync();
}
我从我的行动方法中调用如下: -
Repository repository = new Repository();
public async Task<ActionResult> GetResourceByName(string resourcename)
{
await repository.Save();
}
这是一个正确的方法吗?因为我正在做以下事情: -
我将存储库方法定义为Task&amp;还有Action方法作为Task。所以我应该把它们都作为任务。?
我在动作方法(调用repo方法时)和存储库上两次使用await
?那些await
是多余的?
//请注意,这只是一个存储库方法的简单示例,它仅用于保存模型,但我问的是方法本身,因为我将在更复杂的存储库方法中使用此方法。
答案 0 :(得分:2)
基本上:一旦你去async / await,所有的调用链应该是async / await以避免线程相关的问题......
如果你没有等待,那就叫做:&#34; Fire and Forget&#34;这是不推荐的,因为这个请求将以成功消息返回给用户,但是稍后,你在没有await的情况下进行的调用可能会失败并抛出异常,你不知道那个异常是什么......
答案 1 :(得分:2)
与两个答案相反,两个awaits
不是必需的。只有在您继续之前需要await
的结果时,才需要async
和Task
。如果您不需要该结果,则不需要标记您的方法async
。
这意味着这种方法......
public async Task Save()
{
await t.SaveChangesAsync();
}
可以简化为
public Task Save()
{
return t.SaveChangesAsync();
}
即使这些在功能上是相同的,我喜欢第二个版本,因为它表明Task
是异步工作的识别,而async / await只是编译器等待该工作完成的信号。
答案 2 :(得分:1)
无论其他答案如何,这就是为什么你应该使用await
等等。
ASP.NET具有将在每个await
上捕获的同步上下文,并且将为该上下文发布延续(async
方法的其余部分)。这意味着不仅要进行线程切换,还要使用ASP.NET上下文填充切换到的线程。
如果为异步调用添加后缀(await
调用ConfigureAwait(false)
,则不会发生ASP.NET上下文切换(尽管线程切换会发生)。
因为动作视图引擎很可能需要ASP.NET上下文,所以不能在MVC动作方法上使用ConfigureAwait(false)
。但你应该使用它所调用的所有方法。
所以,你的代码应该是这样的:
public class Repository
{
private Entities t = new Entities();
public async Task SaveAsync()
{
await t.SaveChangesAsync().ConfigureAwait(false);
}
}
Repository repository = new Repository();
public async Task<ActionResult> GetResourceByName(string resourcename)
{
await repository.SaveAsync();
}
因为await
调用ConfigureAwait(false)
之后可能没有ASP.NET上下文,所以你应该从ASP.NET上下文中传递所需的所有内容。
答案 3 :(得分:0)
回答你的问题:
SELECT
T0.C0,
T1.C0,
T2.C0,
CASE
WHEN T1.C0 IS NULL
AND T2.C0 IS NULL THEN 1
END,
CASE
WHEN T2.C0 = 'NM' THEN 'New to PHI'
WHEN T1.C0 IS NOT NULL
OR T2.C0 IS NOT NULL THEN 'Transferred'
ELSE 'New to PHI'
END,
T0.C1
FROM (
SELECT DISTINCT
"Memberships"."MemberNo" AS C0,
COUNT("Memberships"."MemberNo") AS C1
FROM "dbo"."Memberships"
WHERE (
"Memberships"."IsProspect" = N'N'
)
AND (
(
"Memberships"."PaidToDate" > "Memberships"."JoinDate"
OR "Memberships"."HealthTermEntryDate" IS NULL
)
AND "Memberships"."JoinDate" BETWEEN '20150701 00:00:00.0' AND '20160630 23:59:59.997'
)
GROUP BY
"Memberships"."MemberNo"
) T0
LEFT OUTER JOIN (
SELECT DISTINCT
"MembershipPlans"."PrevFundID" AS C0,
"Memberships"."MemberNo" AS C1
FROM "dbo"."Memberships"
INNER JOIN "dbo"."MembershipPlans"
ON (
"Memberships"."MemberNo" = "MembershipPlans"."MemberNo"
)
WHERE (
"Memberships"."IsProspect" = N'N'
)
AND (
"MembershipPlans"."IsPrevCover" IN (N'Y')
)
) T1
ON T0.C0 = T1.C1
LEFT OUTER JOIN (
SELECT DISTINCT
"MembershipUDPs"."Property" AS C0,
"MembershipUDPs"."MemberNo" AS C1
FROM "dbo"."Memberships"
LEFT OUTER JOIN "dbo"."MembershipUDPs"
ON (
"Memberships"."MemberNo" = "MembershipUDPs"."MemberNo"
)
WHERE (
"Memberships"."IsProspect" = N'N'
)
AND (
"MembershipUDPs"."PropertyID" IN (N'TF ')
AND "Memberships"."JoinDate" >= '20150608 00:00:00.0'
)
) T2
ON T0.C0 = T2.C1
有道理。不,它们不是多余的。为了理解你可能(不必要)为什么需要await
两次,我建议你看看这篇文章,它给出了一个非常明确的例子,说明它如何以及为什么有效:
C# async and await: Why Do We Need Them?
如果您想使用存储库并且可能想考虑为您的业务逻辑使用服务,我建议您检查这个易于扩展和通用的项目:
URF - Unit of Work & Repositories Framework
在考虑从头开始开发所有内容之前,您应该检查一下。我真的很喜欢这个项目!