c# - 无法返回类型 IQueryable 或 IEnumerable

标签 c# asp.net-mvc linq wcf entity-framework

由于我无法从 Linq to Entities 查询返回这两种类型中的任何一种,所以我坚持返回列表。

从数据库调用(在单独的 WCF 服务或 DLL 中)返回时, Controller 中的代码失败,因为dbcontext 连接已关闭

注意下面的代码。对于IEnumerable和IQueryable,由于上面的描述,数据没有返回。

MVC Controller 中的方法

// Controller
IEnumerable<ProjectDescription> projectDdl = db.GetProjectDropDownList().AsEnumerable();
// Error coming back because dbcontext connection was closed.
ViewBag.ProjectsCust = new SelectList(projectDdl, "ProjectId", "Name");

WCF服务或DLL中的方法

// WCF Service or DLL 
public IEnumerable<ProjectDescription> GetProjectDropDownList()
{
    try
    {
        //IQueryable<ProjectDescription> project = null;

        using (YeagerTechEntities DbContext = new YeagerTechEntities())
        {
            DbContext.Configuration.ProxyCreationEnabled = false;
            DbContext.Database.Connection.Open();

            IEnumerable<ProjectDescription> project = DbContext.Projects.Select(s =>
                new ProjectDescription()
                {
                    ProjectID = s.ProjectID,
                    Description = s.Description
                }
            );


            return project;
        }


    }
    catch (Exception ex)
    {
        throw ex;
    }
}

我什至尝试了以下在 DB 调用之前建立 DbContext 实例的方法,但实际上尝试将 DbContext 传递给 DB 方法仍然无效。

Controller :

DbContext = new YeagerTechEntities();
IEnumerable<ProjectDescription> projectDdl = db.GetProjectDropDownList(DbContext).AsEnumerable();
ViewBag.ProjectsCust = new SelectList(projectDdl, "ProjectId", "Name");

DbContext.Dispose();

数据库方法:

public IEnumerable<ProjectDescription> GetProjectDropDownList(YeagerTechEntities DbContext)
{
    try
    {
        //IQueryable<ProjectDescription> project = null;


            DbContext.Configuration.ProxyCreationEnabled = false;
            DbContext.Database.Connection.Open();

            IEnumerable<ProjectDescription> project = DbContext.Projects.Select(s =>
                new ProjectDescription()
                {
                    ProjectID = s.ProjectID,
                    Description = s.Description
                }
            );


            return project;
        }


    catch (Exception ex)
    {
        throw ex;
    }
}

除了使用 List 之外,唯一可行的方法是将 DB 方法实际放置在 Controller 中,这显然不是什么好的做法。

这是工作正常的列表约定:

Controller :

IEnumerable<ProjectDescription> projectDdl = db.GetProjectDropDownList();
                ViewBag.ProjectsCust = new SelectList(projectDdl, "ProjectId", "Name");

数据库方法:

public List<ProjectDescription> GetProjectDropDownList()
{
    try
    {
        using (YeagerTechEntities DbContext = new YeagerTechEntities())
        {
            DbContext.Configuration.ProxyCreationEnabled = false;
            DbContext.Database.Connection.Open();

            IEnumerable<ProjectDescription> project = DbContext.Projects.Select(s =>
                new ProjectDescription()
                {
                    ProjectID = s.ProjectID,
                    Description = s.Description
                }
            );

            List<ProjectDescription> myProjects = new List<ProjectDescription>();

            myProjects = project.ToList();

            return myProjects;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

如果有人能向我解释在使用 IQueryable 或 IEnumerable 时正确的模型应该是什么,那很好。但是,在阅读此链接后,似乎 List 绝对是可行的方法: IEnumerable vs IQueryable for Business Logic or DAL return Types

最佳答案

使用 IEnumerable/IQueryable 时代码失败的原因是因为 EF 查询被推迟了;也就是说,在您开始枚举(foreach 等)或“具体化”(ToList() 等)结果之前,它实际上不会针对数据库执行。

  • 因此,因为您创建了一个有效的温度 DbContext用你的using{} , IEnumerable你从函数中传递出来的是地雷——底层 DbContext 在 using block 之后不复存在,任何枚举或具体化集合的尝试都将失败。

  • 即使您创建了 DBContext没有 using block ,你然后继续 Dispose在您执行查询之前就对它进行了处理 - 因此得到了同样的错误。

  • 这是不返回的主要原因之一 IQueryable来自 DAL/存储库 - 因为接收者无法知道查询所依赖的基础上下文在他们尝试使用结果之前是否已经关闭。 IEnumerable好多了(List<T>当然实现了IEnumerable<T>)并且恕我直言,List甚至更好,因为它强制你返回一个完全物化的集合,并让调用者清楚地知道结果不再连接到数据库。

  • 因此您拥有的工作版本可能没问题 - 创建您的上下文,执行查询然后立即实现它,这将执行实际的 SQL,然后断开结果集与数据库的连接.因此该模式适合您。

  • 不过,我建议您使用 IoC 容器(例如 Ninject)为您注入(inject)诸如 DbContext 之类的东西。因为它使您不必担心 DbContext 的生命周期。

希望对您有所帮助。

关于c# - 无法返回类型 IQueryable 或 IEnumerable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19525306/

相关文章:

c# - 使用在多个列上具有主键的 Entity Framework 更新数据库

c# - Entity Framework 4 语句中的多个 "where"条件 - 可能吗?

c# - 有没有工具可以在 Visual Studio 中选择一些代码并让它显示相应的 MSIL?

c# - 有人可以帮我改进这个 linq

c# - 如何在 WinForms 中将字典绑定(bind)到列表框

jquery - 是否有一个可以在模态表单上触发的事件准备就绪?我需要在那里设置下拉列表索引

jquery - Ajax添加了ko.applyBindings后添加的HTML元素不与knockoutjs绑定(bind)

c# - ASP.NET MVC SSL 重定向太多

c# - 下载文件的代码

c# - 如何让 C# Xamarin.Android 应用程序在手机启动时运行?