gpt4 book ai didi

c# - IQueryable 在调用 Count c# 时返回 null

转载 作者:行者123 更新时间:2023-11-30 21:13:45 26 4
gpt4 key购买 nike

我在尝试从以下查询中获取计数时遇到问题:

var usersView = PopulateUsersView(); //usersView is an IQueryable object
var foo = usersView.Where(fields => fields.ConferenceRole.ToLower().Contains("role"));

其中 UsersView 是一个类,它由一个名为 users 的 EF 实体填充(请参阅上面代码中的第一行)

这是 UsersView 类的类定义:

public class UsersView
{
public int UserId { get; set; }
public string Title { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Street1 { get; set; }
public string Street2 { get; set; }
public string City { get; set; }
public string PostCode { get; set; }
public string CountryName { get; set; }
public string WorkPlaceName { get; set; }
public string Gender { get; set; }
public string EMail { get; set; }
public string Company { get; set; }
public string RoleName { get; set; }
public string ConferenceRole { get; set; }
}

正如我所说,尝试执行 foo.Count() 行返回 Null 异常,这可能是因为 ConferenceRole 列在数据库中允许 Null。

现在我无法理解的是,当我直接在 ObjectQuery 上调用相同的查询时,返回的记录计数(即调用 foo2.Count())没有任何异常。

var foo2 = entities.users.Where(fields => fields.ConferenceRole.ToLower().Contains("role"));

是否可以使用 IQueryable usersView 对象代替上面的相同查询?

(对我来说关键是使用usersView对象而不是直接查询entities.users实体)

编辑

下面是 PopulateUsersView 方法的代码

private IQueryable<UsersView> PopulateUsersView()
{
using (EBCPRegEntities entities = new EBCPRegEntities())
{
var users = entities.users.ToList();
List<UsersView> userViews = new List<UsersView>();
foreach (user u in users)
{
userViews.Add(new UsersView()
{
UserId = u.UserId,
Title = u.Title,
Name = u.Name,
Surname = u.Surname,
Street1 = u.Street1,
Street2 = u.Street2,
City = u.City,
PostCode = u.Post_Code,
CountryName = u.country.Name,
WorkPlaceName = u.workplace.Name,
Gender = u.Gender,
EMail = u.E_Mail,
Company = u.Company,
RoleName = u.roles.FirstOrDefault().Name,
ConferenceRole = u.ConferenceRole
});
}
return userViews.AsQueryable();
}
}

谢谢

更新...

谢谢你们,我终于找到了 IQueryable 和 ObjectQuery 对象之间区别的一个很好的答案。

作为解决方案,我正在检查 ConferenceRole 是否为 null,然后使用 contains 方法检查,正如你们许多人所说的那样。

最佳答案

我的 猜测 是您的 PopulateUsersView() 方法实际上正在执行查询并返回 IQueryable Linq-to-Objects 对象 - 而 foo2 行只在 SQL 层执行查询。如果是这种情况,显然 PopulateUsersView() 将是执行 Count

的一种非常低效的方式

要调试这个:


更新

@Ryan - 感谢您将代码发布到 PopulateUsersView

看起来我的猜测是正确的 - 您正在执行一个查询,将整个表返回到一个 List - 然后您使用 Linq2Objects 进一步查询它的这个列表。

@ntziolis 为您的问题提供了一种解决方案 - 在执行 ToLower() 之前测试 null。但是,如果您的唯一要求是Count 非空项目列表,那么我建议您考虑更改PopulateUsersView 方法或更改整体设计。如果您只需要一个 Count,那么确保数据库完成这项工作而不是 C# 代码会更有效率。如果表格有很多行,情况尤其如此 - 例如您绝对不希望将 1000 行数据从数据库中拉回到内存中。


更新 2

请考虑对此进行优化,而不仅仅是做一个简单的 != null 修复。

查看您的代码,有几行会导致多个 sql 调用:

  • CountryName = u.country.Name
  • WorkPlaceName = u.workplace.Name
  • RoleName = u.roles.FirstOrDefault().Name

因为这些是在 foreach 循环中调用的,所以要计算大约 500 个用户的数量,那么您可能会进行大约 1501 次 SQL 调用(尽管一些角色和国家可能会被缓存),返回可能是 1 MB 的数据总共?所有这些只是为了计算一个整数Count

关于c# - IQueryable 在调用 Count c# 时返回 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6690142/

26 4 0