具有延迟加载的WebAPI

时间:2017-09-03 20:28:49

标签: entity-framework asp.net-web-api entity-framework-6 asp.net-web-api2

我正在关注Pluralsight的一个名为"构建Web应用程序&具有实体框架和Web API的服务"。我遵循了教程,但在尝试返回实体框架对象时开始出错 对象已设置为延迟加载。我有两种对象 - Projects和ProjectTasks。我喜欢能够延迟加载的想法,并且有一个web api方法可以在没有项目任务细节的情况下获得项目,而另一个方法可以获得项目列表,其中包含与项目任务相关的详细信息。

然而,每当我试图调用这些方法时,都会抛出一个错误,即已经有一个开放的数据读取器。当我调查这个时,这是因为API触发了延迟加载以序列化内容并试图在后台使用多个数据读取器。在教程中,他从未使用连接字符串显示配置文件,但我能够完成此工作的唯一方法是打开多个活动结果集。当我看到它做了什么,虽然我看到使用它可能会产生负面影响。

我致电:http://localhost:51362/api/Projects/GetAllProjects

所以现在我只是总是包含以下细节。 :

    public IQueryable<Project> GetAllProjects()
    {
        return db.Projects;
    }

这是控制器行动:

public IQueryable<Project> Get()
{
     var projects = repository.GetAllProjects();
     return projects;
}

我以前拥有的是:

    public IQueryable<Project> GetAllProjects()
    {
        return db.Projects;
    }

    public IQueryable<Project> GetAllProjectsWithDetails()
    {
        return db.Projects.Include("ProjectTasks.ProjectTaskItems");
    }

实体框架的虚拟功能是我正在阅读的问题导致的问题。

public class Project
{
    public int Id { get; set; }

    public string ProjectName { get; set; }

    public DateTime StartDate { get; set; }

    public DateTime DueDate { get; set; }

    public decimal EstimatedCost { get; set; }

    public virtual ICollection<ProjectTask> ProjectTasks { get; set; }
}

public class ProjectTask
{
    public int Id { get; set; }

    public string ProjectTaskName { get; set; }

    public virtual Project Project { get; set; }

    public virtual ICollection<ProjectTaskItem> ProjectTaskItems { get; set; }
}

public class ProjectTaskItem
{
    public int Id { get; set; }

    public string ProjectTaskItemName { get; set; }

    public virtual Project Project { get; set; }

    public virtual ProjectTask ProjectTask { get; set; }

}

存储库:

public class ProjectTrackingRepository : IProjectTrackingRepository
{
    private GentrifyAPIContext db;

    public ProjectTrackingRepository(GentrifyAPIContext db)
    {
        this.db = db;
    }

    public IQueryable<Project> GetAllProjects()
    {
        return db.Projects.Include("ProjectTasks.ProjectTaskItems"); ;
    }

    public IQueryable<Project> GetAllProjectsWithDetails()
    {
        return db.Projects.Include("ProjectTasks.ProjectTaskItems");
    }

    public Project GetProject(int id)
    {
        return db.Projects.Include("ProjectTasks.ProjectTaskItems").FirstOrDefault(p => p.Id == id);
    }
}

我看过的一件事是转换为列表并返回IEnumerable而不是IQueryable。但是我不确定我是否因为不使用IQueryable而失去了一些功能。

我想确保我没有遗漏某些东西。在复数视频中他使用这个代码并且它有效 - 但对我来说它并不是 - 似乎必须打开MARS。

这是错误:

{  
   "$id":"1",
   "message":"An error has occurred.",
   "exceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
   "exceptionType":"System.InvalidOperationException",
   "stackTrace":null,
   "innerException":{  
      "$id":"2",
      "message":"An error has occurred.",
      "exceptionMessage":"Error getting value from 'ProjectTasks' on 'System.Data.Entity.DynamicProxies.Project_B44D8796492C46C82F9FF2D753EAC55E7477B5DA96A20EA9E1390986A5A4553E'.",
      "exceptionType":"Newtonsoft.Json.JsonSerializationException",
      "stackTrace":"   at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()",
      "innerException":{  
         "$id":"3",
         "message":"An error has occurred.",
         "exceptionMessage":"An error occurred while executing the command definition. See the inner exception for details.",
         "exceptionType":"System.Data.Entity.Core.EntityCommandExecutionException",
         "stackTrace":"   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)\r\n   at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)\r\n   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__6()\r\n   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)\r\n   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5()\r\n   at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)\r\n   at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)\r\n   at System.Data.Entity.Core.Objects.ObjectQuery`1.Execute(MergeOption mergeOption)\r\n   at System.Data.Entity.Core.Objects.DataClasses.EntityCollection`1.Load(List`1 collection, MergeOption mergeOption)\r\n   at System.Data.Entity.Core.Objects.DataClasses.EntityCollection`1.Load(MergeOption mergeOption)\r\n   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.DeferredLoad()\r\n   at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.LoadProperty[TItem](TItem propertyValue, String relationshipName, String targetRoleName, Boolean mustBeNull, Object wrapperObject)\r\n   at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.<>c__DisplayClass7`2.<GetInterceptorDelegate>b__1(TProxy proxy, TItem item)\r\n   at System.Data.Entity.DynamicProxies.Project_B44D8796492C46C82F9FF2D753EAC55E7477B5DA96A20EA9E1390986A5A4553E.get_ProjectTasks()\r\n   at GetProjectTasks(Object )\r\n   at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)",
         "innerException":{  
            "$id":"4",
            "message":"An error has occurred.",
            "exceptionMessage":"There is already an open DataReader associated with this Command which must be closed first.",
            "exceptionType":"System.InvalidOperationException",
            "stackTrace":"   at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)\r\n   at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)\r\n   at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)\r\n   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)\r\n   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)\r\n   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)\r\n   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)\r\n   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)\r\n   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext`1 c)\r\n   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)\r\n   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)\r\n   at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)\r\n   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)\r\n   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)"
         }
      }
   }
}

0 个答案:

没有答案