2011-03-14 49 views
6

我正在使用EF。这是我的LINQ查询LINQ to EF有什么问题?

public List<Tuple<int, string>> GetList() 
{ 
    return (from c in DALContext.MST 
      select new Tuple<int, string>(c.CD, c.NAME)).ToList(); 
} 

当我打电话的GetList()抛出异常:只有无参构造函数和初始化在LINQ支持到实体

相反,当我重写此查询:

List<Tuple<int, string>> lst = new List<Tuple<int, string>>(); 
var query= (from c in DALContext.MST 
      select new{c.CD, c.NAME}); 
foreach (var item in query) 
{ 
    lst.Add(new Tuple<int,string>(item.CD,item.NAME)); 
} 
return lst; 

它只是正常工作。我的第一个查询有什么问题?

回答

11

其他的答案是什么回事正确的,但我没有看到任何人提起,使你的代码工作的最佳方法:AsEnumerable()

public List<Tuple<int, string>> GetList() 
    { 
     return (from c in DALContext.MST.AsEnumerable() 
       select Tuple.Create(c.CD, c.NAME)).ToList(); 
    } 

AsEnumerable方法作为代码,应该是之间的边界转换为SQL并在数据库服务器中执行,以及在从数据库获得响应后应在内存中执行的代码。把它放在表名之后告诉EF从MST表中获取所有记录,然后运行下面的代码,该代码根据返回的值创建元组。

我将new Tuple<int, string>更改为Tuple.Create,主要是因为我不喜欢输入泛型类型参数。

+1

“AsEnumerable()”与使用“ToList()”还是“ToArray()”有什么不同? – Despertar 2012-12-16 01:35:16

+1

@Despertar - ToList()和ToArray()必须遍历查询结果以构建列表或数组。在上面的例子中,如果用'ToList()'替换'AsEnumerable()',那么你会遍历结果两次。使用'AsEnumerable()'你只需循环一次,因为'AsEnumerable()'不会消耗序列。 – 2012-12-16 19:27:11

6

LINQ to EF处理查询有点不同于LINQ to SQL。在LINQ to EF,你不能把一个带参数的构造函数在LINQ的表情,就像你在代码的第一位在这里做的:

from c in DALContext.MST 
select new Tuple<int, string>(c.CD, c.NAME) 

元组的构造函数接受两个参数,这是不允许的在LINQ到EF。

原因解释here

这部分是想 LINQ到实体更明确 约之间您的查询字词部分 执行服务器 ,哪些在边界的问题部分在客户端执行。

使用LINQ到SQL,例如,它是 可以写一个LINQ查询其 不仅涉及数据从服务器 和功能的服务器上,但也 功能,只能在 客户端和执行将它们混合在一起,即 。然后,LINQ to SQL提供程序 将尽最大努力解决 问题,并执行它可以在服务器上运行的部分以及在客户端上运行 的其他部分。这很好,因为它 很容易只写任何你想要的查询 ,并且如果可能的话会起作用。在另一方面,它 不是那么好,如果你不小心写 查询哪里可以 在服务器上执行的唯一部分是返回的所有数据 中的一个或多个表中的最 最基本的东西,然后有 所有过滤发生在客户端 (带有非常讨厌的后果)。

使用LINQ to Entities,边界 更明确。当你写一个 LINQ查询针对LINQ to实体 IQueryable的执行,整个 查询在服务器上执行,而如果 查询的某些部分不能 在服务器上执行,那么 明确的边界必须创建 类似ToQueryable()或 ToList()。一旦执行该查询 并检索到数据,则可以使用LINQ to Objects 进一步优化 查询是否如此选择。这种方式 你明确知道你的 界限是哪里,并且它更容易 跟踪性能问题和 一样。 的一个相关限制是,实体的LINQ 中的select语句可以创建匿名类型 或其他类型,只要它们具有默认构造函数 参数。这最大限度地减少了选择语句具有主要 副作用的机会 。

1

你的类需要有LINQ到EF参数的构造函数,你必须初始化它是这样的:

public List<Tuple<int, string>> GetList() 
{ 
    return (from c in DALContext.MST 
      select new Tuple<int, string>(){CD = c.CD, Name = c.NAME}).ToList(); 
} 

编辑:

如果您未在位置添加无参数构造函数TUPLE(这里Tuple不是一个类本身),那么你没有选择使用Linq到EF,但要做为一个两步过程:

public List<Tuple<int, string>> GetList() 
{ 
    List<MST> mstList = (from c in DALContext.MST 
         select c).ToList(); 

    List<Tuple<int, string>> tupleList = new List<Tuple<int, string>>(); 

    mstList.foreach(c => tupleList.add(new Tuple(c.CD, c.Name))); 

    return tupleList; 
} 
+0

不幸的是,这不起作用,因为大括号只是用于设置属性的语法糖,而元组没有可分配的CD或Name属性(或者任何可分配的属性)。 – 2011-03-14 06:09:33

2

或者你可以只写

var query= (from c in DALContext.MST 
      select new{c.CD, c.NAME}).ToList().Select(x=>new Tuple(x.CD, x.NAME)); 

这样做的好处是只从DB带给你所需要的两列。

+0

关于只选择你需要的两列,这是一个很好的观点,但我仍然选择'AsEnumerable',然后'ToList'两次调用'ToList'。 – 2012-07-24 00:41:15