使用带有导航属性的ToListAsync()

时间:2016-07-03 08:04:25

标签: asp.net-mvc entity-framework

我正在使用ASP.NET MVC和Entity Framework。 我有一个名为“AllUserData”的实体。 我有一个名为“Genres”的第二个实体。表格中的每一行都是一种流派。

这两个实体具有一对多的关系。所以在“AllUserData”类的类定义中,我有   public virtual ICollection PreferredGenres {get;组; }

我能够使用

成功阅读每个用户首​​选的类型
AllUserData aud = db.AllUserData.Single(b => b.UserId == currentUserId);
var chosengenres = aud.PreferredGenres.ToList()

但我无法使用

AllUserData aud = db.AllUserData.Single(b => b.UserId == currentUserId);
var chosengenres = await aud.PreferredGenres.ToListAsync()

Visual Studio说“ICollection不包含'ToListAsync'的定义,最好的扩展方法重载'QueryableExtensions.ToListAsync(IQueryable)'需要一个'IQueryable'类型的接收器。

为什么会这样?两者之间的唯一区别是,在一种情况下,我使用了ToList(),而在另一种情况下,我使用了ToListAsync()。

异步方法可以不与导航属性一起使用吗?在现实生活中,很多情况下各种实体之间存在关系;使用这些关系访问属性时,是否可以使用异步方法?这有什么办法吗?如果可能的话,我宁愿异步做事。

2 个答案:

答案 0 :(得分:2)

您的导航属性已被声明为ICollection,是实体属性的标准 - 编译器不会满意。

但是,你可以在导航集合和ToListAsync()之间使用AsQueryable或其他Select()(如果这对你的需要有意义)获得IQueryable。

ToList()可以在IEnumerable上运行(包括ICollection和IQueryable)。 ToListAsync()只能用于IQueryable,因此来自VS的消息。 “为什么”可能在于实施细节。

答案 1 :(得分:0)

好吧,似乎实体框架不允许以这种方式异步调用导航属性。

对我来说有用的是在开始时加载导航属性。 (感谢用户daf向我发送正确的方向)。

所以而不是

// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.4")

// Web plugins
addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.1.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.3")
addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.7")
addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0")
addSbtPlugin("org.irundaia.sbt" % "sbt-sassify" % "1.4.2")

// Play enhancer - this automatically generates getters/setters for public fields
// and rewrites accessors of these fields to use the getters/setters. Remove this
// plugin if you prefer not to have this feature, or disable on a per project
// basis using disablePlugins(PlayEnhancer) in your build.sbt
addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0")

哪个不起作用,我可以这样做:

AllUserData aud = await db.AllUserData.SingleAsync(b => b.UserId == currentUserId);
var usergenres = await aud.PreferredGenres.ToListAsync(); 

这样,第一个查询要求通过使用.Include()的急切加载从数据库中提取所有必要信息,并且由于.SingleAsync()的用户而异步执行。下一个语句使用.ToList(),但不应该再次访问数据库,因为数据已经急切加载,所以它是异步的并不重要。现在整个操作都是异步的。

我也意识到之前在StackOverflow上已经提到了同样的问题;根据您使用的搜索字词,有点难以找到:Entity Framework Designer First get navigation property as Tasks。所选答案提供了4种不同的解决方案,其中第一种解决方案类似于我现在使用的解决方案。

在定义实体类时,似乎也可以将导航属性指定为异步 - 请参阅标题为" Async Lazy Loading"在此页面上:here示例代码段演示了如何为单个导航属性执行此操作;我不知道是否可以为ICollection导航属性做,这是我需要的,但我也没有做任何进一步的挖掘。