2

我已经开发了一个项目,在Asp.Net Web API中使用,请遵循实体框架代码优先的方法。实体框架代码 - 首先与本地数据库一起工作,但部署到Azure时发生错误

我已经在本地机器上用Visual Studio 2013中的本地数据库对它进行了测试,并且它可以正常工作。

当我替换连接字符串并将数据库部署到Azure时,问题就出现了。我能够执行一些查询,但没有其他。

例如,如果我在浏览器中输入http://my-site/api/users/1我会得到预期的结果。然而,查询http://my-site/api/users/回到我与JSON序列化的错误:

{ "$id" : "1", 
    "ExceptionMessage" : "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.", 
    "ExceptionType" : "System.InvalidOperationException", 
    "InnerException" : { "$id" : "2", 
     "ExceptionMessage" : "Error getting value from 'Devices' on 'System.Data.Entity.DynamicProxies.User_50420314CCDC05AAF3288A574C1CBB8436C09BAEF7539C2795445FCBA161AC99'.", 
     "ExceptionType" : "Newtonsoft.Json.JsonSerializationException", 
     "InnerException" : { "$id" : "3", 
      "ExceptionMessage" : "An error occurred while executing the command definition. See the inner exception for details.", 
      "ExceptionType" : "System.Data.Entity.Core.EntityCommandExecutionException", 
      "InnerException" : { "$id" : "4", 
       "ExceptionMessage" : "There is already an open DataReader associated with this Command which must be closed first.", 
       "ExceptionType" : "System.InvalidOperationException", 
       "Message" : "An error has occurred.", 
       "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 asyncWrite)\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.<>c__DisplayClassb.<Reader>b__8()\r\n at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TInterceptionContext,TResult](Func`1 operation, TInterceptionContext interceptionContext, Action`1 executing, Action`1 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)" 
      }, 
      "Message" : "An error has occurred.", 
      "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__DisplayClassb.<GetResults>b__a()\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__DisplayClassb.<GetResults>b__9()\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.Load()\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.User_50420314CCDC05AAF3288A574C1CBB8436C09BAEF7539C2795445FCBA161AC99.get_Devices()\r\n at GetDevices(Object)\r\n at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)" 
     }, 
     "Message" : "An error has occurred.", 
     "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 Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)\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.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__19.MoveNext()" 
    }, 
    "Message" : "An error has occurred.", 
    "StackTrace" : null 
} 

这个问题真的讨厌我,因为正如我所提到的,与本地数据库工作正常。本地和Azure生成的数据库似乎是平等的。所以,我无法猜测问题出在哪里。

+0

在两个数据库中确认数据是否相同?由于数据不同,这可能只是一个问题。另外,您是否可以发布用户和设备实体的相关代码,以及流畅的API配置(如果有)? –

+0

我现在没有代码,但'User'有'ICollection '类型的'Devices'属性。 'Device'也有一个'User'类型的属性。即每个设备都有一个用户,而一个用户可以拥有很多设备。 – anderZubi

回答

2

添加.ToArray()的结果,我从我的GETALL()方法返回的解决了这个问题:

public IEnumerable<TEntity> GetAll() 
    { 
     return _dbContext.Set<TEntity>().ToArray(); 
    } 

但是,我仍然不知道为什么它是与本地数据库的工作,而不是与部署到Azure的数据库。

添加MultipleActiveResultSets=True也解决了我的问题。但是由于我不知道启用该功能需要什么,我选择了第一个选项。

+0

Yeap。 .ToArray(),.ToList(),.Single(),所有这些都会返回对象。你不能返回的是一个实体框架代理。我建议你映射到POCO以避免这种情况,但以这种方式返回也会起作用。 –

+0

当您有延迟加载的子对象时,MultipleActiveResultSets是必需的。这允许EF打开一个结果集(用于父对象)并打开新结果集以获取子对象。 – howcheng

3

答案是错误信息告诉你的。它不能将实体框架代理序列化为JSON。你应该映射到POCO类和返回他们:

//poco 
    public class PersonPoco 
    { 
     public string FirstName {get;set;} 
     public string LastName {get;set;} 
    } 

//控制器

public IEnumerable<PersonPoco> Get() 
{ 
    var person = _personRepository.FindAll(); 

    person.Select(x=> new PersonPoco() { 
    FirstName = x.f_name, 
    LastName = x.l_name 
    }).ToList(); 
} 

可以使用AutoMapper要做到这一点的转换,您可以创建扩展方法做这种转换。无论如何,这只是一个样本。

+0

如果这是问题,我会检查明天。但是,那么,为什么当我使用本地数据库时它会工作? – anderZubi

+1

很好的问题。我几乎可以肯定它不会在本地工作。 –

+0

这就是为什么我想知道它是否与数据有关。如果查询没有在localdb上返回任何数据,那么将不会有序列化错误。顺便说一下,另一个解决方案是关闭动态代理并使用显式的'.include'语句。 –

相关问题