2

首先,我做了一些寻找这个问题的答案......但我找不到任何东西,因为我不知道我正在使用的功能是什么。

以下代码中的 DBEntities 是由 devart 为 Oracle 数据库连接生成的。

为什么第一个示例有效,而第二个示例只给我一个 System.NullReferenceException?

有效代码:

using (DBEntities context = new DBEntities())
{
    var infos = (from info in context.Infos
                 where info.Index == index
                 orderby info.Name
                 select new
                 {
                     Name = info.Name,
                     MRN = info.MRN,
                     UnitNumber = (info.UnitNum == null) ? -1 : (decimal)info.UnitNum,
                     UnitName = (info.UnitName == null) ? String.Empty : info.UnitName
                 }).Distinct();

    foreach (var info in infos)
    {
        // *do stuff*
    }
}

给出异常的代码(只有在达到 foreach 时才会看到异常):

using (DBEntities context = new DBEntities())
{
    var infos = (from info in context.Infos
                 where info.Index == index
                 orderby info.Name
                 select new Member()
                 {
                     Name = info.Name,
                     MRN = info.MRN,
                     CurrentUnit = new Unit()
                     {
                         UnitNumber = (info.UnitNum == null) ? -1 : (decimal)info.UnitNum,
                         UnitName = (info.UnitName == null) ? String.Empty : info.UnitName
                     }
                 }).Distinct();

    foreach (Member info in infos)
    {
        // *do stuff*
    }
}

编辑: 我想补充一点,这也有效:

using (DBEntities context = new DBEntities())
{
    var infos = (from info in context.Infos
                 where info.Index == index
                 orderby info.Name
                 select new Member()
                 {
                     Name = info.Name,
                     MRN = info.MRN
                 }).Distinct();

    foreach (Member info in infos) //Exception is thrown here.
    {
        // *do stuff*
    }
}
4

2 回答 2

2

第一个有效,因为您可以从 SQL 返回那些匿名类型,并且 EF 可以为整个表达式生成 SQL 语句。第二个没有,因为您无法在 SQL 中创建 Member 类的实例。如果您强制进行枚举(使用 AsEnumerable()),您可以创建 Member 值客户端。

异常总是会在枚举点被抛出,因为 LINQ 在设计上是完全“懒惰的”。如果您想强制它在您创建表达式时发生(例如,出于测试目的),请添加.ToList()到它的末尾。

于 2012-04-06T22:23:25.750 回答
0

代替

foreach (Member info in infos) //Exception is thrown here.
{
    // *do stuff*
}

利用

foreach (var info in infos) //Valid.
{
    // *do stuff*
}

这是因为infos返回匿名结果。这不是完全的Member集合类。

于 2012-04-06T22:27:14.560 回答