我有一个实体框架模型(已排除某些属性以保持简单):
public class Media
{
public int MediaID { get; set; }
public ICollection<Track> Tracks { get; set; }
public ICollection<RelatedMedia> RelatedMedias { get; set; }
}
然后我有我的DbContext:
public class MediaServiceContext : DbContext
{
public DbSet<Media> Medias { get; set; }
}
然后,我可以使用以下内容检索数据,效果很好:
public Media Media_Get(int id)
{
using (MediaServiceContext mc = new MediaServiceContext())
{
return mc.Medias.Include("Tracks").Include("RelatedMedias").Single(m => m.MediaID == id);
}
}
我的问题是,在某些情况下,我可能不想加载一个或两个相关实体,具体取决于我的应用程序的哪个部分正在调用此代码;如何使包含动态?
我试过这个:
public Media Media_Get(int id, bool includeRelated, bool includeTracks)
{
using (MediaServiceContext mc = new MediaServiceContext())
{
IQueryable<Media> query = mc.Medias;
if (includeRelated)
query = query.Include("RelatedMedias");
if (includeTracks)
query = query.Include("Tracks");
return query.Single(m => m.MediaID == id);
}
}
...但是我收到了“指定的无效投射”例外。
我也尝试了this提出的解决方案,但它产生了一个'无法将DbQuery转换为ObjectQuery'异常。将链接解决方案中的扩展方法从'(ObjectQuery)source'更改为'(DbQuery)source'然后导致相同的'指定的强制转换为无效' 例外。
我已经寻求解决方案,但没有运气。任何帮助将不胜感激。
修正案 - 这是堆栈跟踪:
at System.Data.SqlClient.SqlBuffer.get_Int64()
at lambda_method(Closure , Shaper )
at System.Data.Common.Internal.Materialization.Coordinator.HasNextElement(Shaper shaper)
at System.Data.Common.Internal.Materialization.Shaper`1.RowNestedResultEnumerator.MoveNext()
at System.Data.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.TryReadToNextElement()
at System.Data.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.MoveNext()
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
at API.Areas.V1.Models.RetailerManager.Media_Get(Int32 id, String retailerKey, Boolean includeLicenses, Boolean includeProperties, Boolean includeRelated, Boolean includeTracks) in C:\Users\garth\Documents\Development\WebApplications\api\Areas\V1\Models\RetailerManager.cs:line 28
at API.Areas.V1.Controllers.RetailerController.Media(Nullable`1 id, String httpVerb, Boolean includeLicenses, Boolean includeProperties, Boolean includeRelated, Boolean includeTracks) in C:\Users\garth\Documents\Development\WebApplications\api\Areas\V1\Controllers\RetailerController.cs:line 25
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
答案 0 :(得分:1)
您的堆栈跟踪显示.SingleOrDefault()
导致此异常,但我在您的代码中看不到.SingleOrDefault()
。
我确实看到了这个:
return query.Single(m => m.MediaID == id);
Media.MediaID
可能是long
而不是int
吗?
<强>更新强>
作为回答原始问题的另一种选择,我answered a question a couple of weeks ago in relation to this。我的答案中的示例代码与动态排序有关,但我们使用非常相似的模式进行动态预先加载(请参阅我的回答后的第一条评论)。
而不是像这样的方法签名:
public Media Media_Get(int id, bool includeRelated, bool includeTracks)
您的签名看起来更像是这样:
public Media Media_Get(MediaGetter mediaGetter)
......你会像这样使用它:
var media = someInstance.Media_Get(
new MediaGetter { ID = id, }
.EagerLoad(m => m.Tracks)
.EagerLoad(m => m.RelatedTracks)
);