【问题标题】:How to return IEnumerable DbSet in web api get?如何在 web api get 中返回 IEnumerable DbSet?
【发布时间】:2013-04-11 20:08:11
【问题描述】:

“用户”类由实体框架模型首先设计者自动生成。

public partial class user
{
    public user()
    {
        this.distributorDevice = new HashSet<distributorDevice>();
        this.managerDevice = new HashSet<managerDevice>();
        this.logUserLogin = new HashSet<logUserLogin>();
        this.logUserOperates = new HashSet<logUserOperates>();
        this.clientApp = new HashSet<clientApp>();
    }

    public int Id { get; set; }
    public string name { get; set; }
    public byte[] password { get; set; }
    public bool isActive { get; set; }
    public System.DateTime RegisterTime { get; set; }
    public int permissionId { get; set; }
    public System.DateTime lastLoginTime { get; set; }

    public virtual permission permission { get; set; }
    public virtual ICollection<distributorDevice> distributorDevice { get; set; }
    public virtual ICollection<managerDevice> managerDevice { get; set; }
    public virtual ICollection<logUserLogin> logUserLogin { get; set; }
    public virtual ICollection<logUserOperates> logUserOperates { get; set; }
    public virtual ICollection<clientApp> clientApp { get; set; }
    public virtual customerDevice customerDevice { get; set; }
}

如果我这样写

 public class UserController : ApiController
 {
 public IEnumerable<user> Get()
    {
        List<user> users = new List<user>();
        return user;
    }
 }

当我在资源管理器中访问“localhost:3700/api/user”时,它可以工作。

<ArrayOfuser xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/UpdateServer.Model"/>

如果我这样写

    public IEnumerable<user> Get()
    {
        using (var mydb = new ModelContainer())
        {
            return mydb.userSet.AsEnumerable();
        }
    }

当我在资源管理器中访问“localhost:3700/api/user”时,我收到错误消息:

103 (net::ERR_CONNECTION_ABORTED)

按照建议,我应该使用 ToList() 而不是 asEnumerable,我像这样更改代码

using (var mydb = new ModelContainer())
        {
            var users = mydb.userSet.ToList();
            return users;
        }

但在资源管理器中仍然出现同样的错误

103 (net::ERR_CONNECTION_ABORTED)

我添加了一个中断

return users;

发现用户已经从DB获取数据,但没有正确返回给客户端。

我做了更多测试,我添加了一个权限名称为“Admin”的用户,如果我使用下面的代码,没有找到用户,它正确响应客户端。

var users = mydb.userSet.Where(p=>p.permission.name == "Administrator").ToList();
return users;

如果我这样写

var users = mydb.userSet.Where(p=>p.permission.name == "Admin").ToList();
return users;

返回客户端失败,报错

103 (net::ERR_CONNECTION_ABORTED)

【问题讨论】:

  • 谢谢,我用 ToList() 代替 AsEnumerable(),还是不行。
  • 您是否使用了任何导航属性,我是的,您必须急切地加载它们?
  • 谢谢,当我删除导航属性时,它可以工作。在google了一些关于如何处理它之后,我发现我应该添加DTO层。然后新的问题来了。很多写手说POCO比DTO好,但我觉得DbContext就是POCO,那我应该用DTO+POCO吗?或者我完全走错了路。有没有办法只使用 DbcontextAPI?
  • 恕我直言,最重要的是完美控制数据库上下文的范围。 DTO 是实现这种控制的一种方式,学校方式。总是恕我直言,POCO 是一种允许实例化对象的类型/类。对象(PO​​CO 类的实例)可以是与数据库上下文相关的实体,也可以是与数据库上下文不相关(分离)的 DTO。您必须使用或不同的类型/类来推动从实体到 DTO 的转换。

标签: c# .net entity-framework asp.net-web-api


【解决方案1】:

EF 使用延迟加载。这意味着 EF 在您尝试使用结果之前实际上不会调用数据库。

要解决此问题,您可以使用ToList()。不像AsEnumerable ToList 会立即执行查询。

另一个选项是不释放上下文。虽然这看起来可能是错误的,但您实际上可以让 db context 保持活动状态,并在您不再使用任何返回的用户对象时让垃圾收集器获取它。

【讨论】:

  • 谢谢,我用 ToList() 代替 AsEnumerable(),还是不行。
  • 让数据库上下文保持打开状态直到垃圾回收是耗尽连接池的好方法。
  • 另外,ToList 首先完全否定了暴露IQueryable 的性能优势...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-03
  • 1970-01-01
  • 2022-07-26
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多