【问题标题】:Web API with separate entity framework data layer具有独立实体框架数据层的 Web API
【发布时间】:2016-11-11 20:38:28
【问题描述】:

我有一个使用默认 VS15 模板和“defaultconnection”连接字符串的 asp.net 身份设置的 web api。我在解决方案中添加了一个类库,并在此基础上从我的数据库中添加了一个实体框架 ado.net 模型。我将类库的 app.config 文件中的连接字符串添加到我的 Web 配置中。

API 上的 Web.config 连接字符串:

<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=&quot;data source=MyDatabase;initial catalog=Dev;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" 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 中引用它?

【问题讨论】:

  • 我猜你正在使用延迟加载,所以当从 using 块内部返回时,包装的上下文在获取延迟加载的属性之前被处理。检查this。也许是这样。
  • 默认情况下,实体框架使用延迟加载,除非通过禁用它来指定。

标签: c# asp.net asp.net-mvc entity-framework asp.net-identity


【解决方案1】:

在来自 .Net 运行时空间中的 Get --a 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());

然后您可以完全控制通过网络发送的内容,不会发生延迟加载意外。

【讨论】:

  • 非常感谢您的解释,我继续定义了一个 DTO,它运行良好。
猜你喜欢
  • 2012-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-28
  • 2010-09-09
  • 2014-05-25
相关资源
最近更新 更多