我有一个web api,它是使用默认的VS15模板和一个"defaultconnection"连接字符串的asp.net身份设置。我在解决方案中添加了一个类库,并在此基础上从我的数据库中添加了一个实体框架ado.net模型。我在类库的app.config文件中添加了一个连接字符串到我的web配置。
网络。配置api连接字符串:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=MyDatabase;Initial Catalog=Dev;Integrated Security=True" providerName="System.Data.SqlClient" />
<add name="IBPC_DevEntities" connectionString="metadata=res://*/IBPCDataModel.csdl|res://*/IBPCDataModel.ssdl|res://*/IBPCDataModel.msl;provider=System.Data.SqlClient;provider connection string="data source=MyDatabase;initial catalog=Dev;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
对于一个测试,我试图从我的api的控制器获取用户信息的请求:
[Authorize]
public HttpResponseMessage Get(int id)
{
using (IBPC_DevEntities entity = new IBPC_DevEntities())
{
return Request.CreateResponse(HttpStatusCode.OK,
entity.User.FirstOrDefault(u => u.NDBHUserID == id));
}
}
当我在Postman中发送请求(带有授权令牌)时,它响应一个InnerException,表示"ObjectContext实例已被处置,不能再用于需要连接的操作。"
我如何在自己的项目中首先使用数据库EF6,并从使用默认连接进行身份验证的API中引用它?
在Get
(. net运行时空间中的User
对象)的返回值和API消费者端的接收值之间涉及到大量中间件。首先发生的事情之一是User
对象被序列化为Json。
虽然Json序列化器(Json.Net)是一个非常聪明的野兽,但它不知道加载和未加载导航属性之间的区别。因此,如果您的User
具有类似Accounts
的属性(只是一个示例),它也将尝试序列化该属性。这会触发延迟加载,导致这个臭名昭著的异常。
一个快速的修复方法是禁用延迟加载:
using (IBPC_DevEntities entity = new IBPC_DevEntities())
{
entity.Configuration.LazyLoadingEnabled = false;
return Request.CreateResponse(HttpStatusCode.OK,
entity.User.FirstOrDefault(u => u.NDBHUserID == id));
}
一个更好的解决办法是使用视图模型/DTO对象:
return Request.CreateResponse(HttpStatusCode.OK,
entity.User.Where(u => u.NDBHUserID == id)
.Select(u => new UserDto { Name = u.Name, .... })
.FirstOrDefault());
这样,您就可以完全控制将通过网络发送的内容,并且不会发生延迟加载意外。