2012-04-06 68 views
2

首先,我做了一些搜索这个问题的答案...但我找不到任何东西,因为我不知道我用什么功能被称为。LINQ:为什么我不能在返回的对象中声明新对象?

以下代码中的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

你有什么异常? – Thebigcheeze 2012-04-06 22:20:07

+0

@Thebigcheeze System.NullReferenceException – bsara 2012-04-06 22:23:10

+0

是否确定你的集合包含数据? – Tigran 2012-04-06 22:25:09

回答

2

第一个工作原理是因为您可以从SQL返回这些匿名类型,并且EF可以为整个表达式生成一条SQL语句。第二个不是因为你不能在SQL中创建成员类的实例。如果你强制枚举发生(使用AsEnumerable()),你可以创建Member value客户端。

在枚举时总会抛出异常,因为LINQ在设计上完全是'懒惰'的。如果你想在创建表达式的时候强制它发生(为了测试的目的,比如说),然后在其末尾添加.ToList()

+0

所以你说我只是'与使用实体使用LINQ时使用CurrentUnit创建对象的新实例,但如果我正在Enumerable对象上使用它,我可以创建该实例吗?只是澄清。 – bsara 2012-04-06 22:25:11

+0

不,他说,在你的特定情况下,你必须强迫Linq执行,告诉它你现在需要价值。 – 2012-04-06 22:26:21

+2

始终考虑查询表达式的哪些部分将在数据库上进行评估,以及哪些部分将在客户端上评估。在.ToList(),.ToArray(),.AsEnumerable()之前的任何内容都会在SQL Server上发生,所以如果你的表达式不能被评估,那么它将会失败。 EF没有尝试弄清楚在哪里放置边界,只是盲目地认为它可以尽可能地在SQL中做。 – 2012-04-06 22:27:24

0

而不是

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

使用

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

这是因为infos回报anonymus结果。这不是完全Member集合类。

+0

但是在'foreach(Member ...')的例子中,查询实例化'Member'实例,而不是匿名实例。 – phoog 2012-04-06 22:35:10

+2

@phoog。您不是迭代完全限定的成员集合类,如List 集合类。为什么你必须使用var而不是Member类 – wonde 2012-04-06 22:38:19

+1

这是不正确的,如果你用'select new Member()'作为select子句进行查询,它将返回一个'IEnumerable '和'foreach(Member。 ..'会工作得很好,另一个原因是异常(参见Hightechrider的答案) – phoog 2012-04-06 22:40:05

相关问题