繁体   English   中英

什么是 function 评估需要所有线程运行?

[英]What is the function evaluation requires all threads to run?

我刚刚制作了一张桌子 Cust 和 Ado.net 并创建了一个 dbEntity 来使用 LINQ

但是我收到了这个错误,我无法获取记录。

  protected void Page_Load(object sender, EventArgs e)
    {

        SSEntities db = new SSEntities();


        var a = from tb in db.Custs
                select tb;

    }

连接字符串——

    <add name="SSEntities" connectionString="metadata=res://*/DbModel.csdl|res://*/DbModel.ssdl|res://*/DbModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=XYZ\SQLEXPRESS;initial catalog=SS;persist security info=True;user id=sa;password=La123;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

错误 - function 评估需要所有线程运行

但这有效

     protected void Page_Load(object sender, EventArgs e)
    {

        SSEntities db = new SSEntities();


        var a = db.Custs.FirstOrDefault();

    }

您必须了解 LINQ 使用的延迟执行。

假设db.Custs是一个 object 实现IQueryable<Cust>或类似的东西。

如果您在第一个示例中检查a的类型,您会看到它是一个IQueryable<Cust> 第二个示例中的一个是Cust

如果您检查 LINQ 方法,您会注意到它们有两组:返回IEnumerable<TResult> (或IQueryable<TResult> )的一组和不返回的一组。

Select, Join, GroupBy是第一组的示例。 他们不执行查询。 它们不代表获取的数据,它们代表select 数据的潜力并枚举它。

只要您只连接该组中的函数。 不查询您的数据来源。 这个来源通常是一个数据库,但它可以是任何可枚举的、CSV 文件阅读器、JSON 文件、来自互联网的信息。 在 LINQ 术语中,我们说这些方法使用延迟执行。 您可以在该方法的每个描述中找到该术语。

第二组方法的示例是ToList, FirstOrDefault, Count, Any :返回不是IQueryable<...> 执行其中一个方法将开始枚举作为输入源的 IEnumerable/IQueryable:将获取第一个元素,如果有,并且如果方法需要,将获取序列的其他元素。

回到你的问题

您的第一个页面加载将创建查询。 创造了从数据库中获取数据的潜力。 唉,你忘了执行查询。 如果您调试程序,并在断点处停止所有线程,并希望检查 a 的值,您希望查看 object a的属性。 唉,你的调试器愿意向你展示简单属性的结果,但是联系数据库对它来说太难了。

因此,如果您真的想在调试时查看数据库查询的结果,则必须通过添加第二组的方法来执行查询。 大多数情况下,人们会临时添加ToList()

在第二个示例中,您使用了第二组的方法:执行查询,并将结果放入本地 memory:调试器可以访问数据,因为它只需要检查一些 memory。

因此,调试解决方案很简单:在检查之前添加ToList

改进

现在,您知道第一个示例中的变量a表示获取数据的可能性,而不是获取的数据本身。 您显然简化了问题的代码,您想对数据做一些事情。

  • 我很确定 SSEntities 实现了IDisposable 您应该在不再需要它时立即将其丢弃。
  • 确保在处置 SSEntities 之前获取数据(执行查询)。

通常人们使用以下结构来确保 object 在所有情况下都正确配置:

using (SSEntities db = new SSEntities())
{
    var myQuery = db.Custs.Select(cust => new {...});

    // execute the query:
    var fetchedData = myQuery.ToList();
}

请注意以下陷阱:

IQueryable<Cust> GetCustomers()
{
    using (SSEntities db = new SSEntities())
    {
        return db.Custs.Select(cust => new {...});
    }
}

查询未执行,但您已处置 SSEntities。 你的编译器不会抱怨,你会在运行时得到一个异常。

正确的解决方案是让您的调用者创建和处理与数据库的连接,您只需提供选择:

static IQueryable<Cust> GetCustomersByPostCode(this IQueryable<Cust> customers,
       PostCode postCode)
{
    return customers.Where(customer => customer.PostCode == postCode)
                    .Select(customer => new {...});
}

用法:

protected void Page_Load(object sender, EventArgs e)
{
    List<Customer> customers = null;
    using (SSEntities db = new SSEntities())
    {
    
        PostCode postCode = ...
        customers = db.Customers.GetCustomersByPostCode(postCode).ToList();
    }

    // the database is disposed, cannot be used anymore
    // customers already fetched, can still be used:
    ProcessFetchedCustomers(customers);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM