你能解释一下为什么示例#1因“No Translation to SQL”失败而示例#2工作正常吗?
All in Repository:
EX#1:
public DomainPerson GetBestPerson()
{
var person= GetPeople().Where(p=>p.Quality=="Best").SingleOrDefault();
return person;
}
public IQueryable<DomainPerson> GetPeople()
{
var people= from p in Data.Persons
select MapToDomain(p);
return people;
}
private DomainPerson MapToDomain(Data.Person dataPerson)
{
DomainPerson domainPerson= new DomainPerson{
Id=dataPerson.Id,
Name=dataPerson.Name,
Quality=dataPerson.Quality,
};
return domainPerson;
}
EX#2
public DomainPerson GetBestPerson()
{
var person= GetPeople().Where(p=>p.Quality=="Best").SingleOrDefault();
return person;
}
public IQueryable<DomainPerson> GetPeople()
{
var people= from p in Data.Persons
select new DomainPerson{
Id=dataPerson.Id,
Name=dataPerson.Name,
Quality=dataPerson.Quality,
};
return people;
}
答案 0 :(得分:1)
在第一个中,GetPeople()生成的表达式树包含MapToDomain,它无法转换为SQL表达式。
考虑更改MapToDomain,以便返回IQueryable&lt;&gt; (*并修复对MapToDomain()的剩余调用,因此他们调用SingleOrDefault()。比解释更简单,我没有编译它,因为我没有可用的底层对象:
public DomainPerson GetBestPerson()
{
var person= GetPeople().Where(p=>p.Quality=="Best").SingleOrDefault();
return person;
}
public IQueryable<DomainPerson> GetPeople()
{
return MapToDomain(Data.Persons);
}
IQueryable<DomainPerson> MapToDomain(IQueryable<Person> persons)
{
return persons.select(dataPerson => new DomainPerson{
Id=dataPerson.Id,
Name=dataPerson.Name,
Quality=dataPerson.Quality,
};
}
答案 1 :(得分:1)
原因是LINQ to SQL的工作原理是将表达式树(Expression<Func<T>>
)转换为SQL并在服务器上运行它。您在#1中引用的方法将编译为IL。 LINQ to SQL无法从其正文中获取表达式树表示。
第二个例子并没有真正编译成IL。它存储在可以在运行时读取和转换的数据中。 My answer for this question详细解释了这一点。
答案 2 :(得分:1)
正如其他人所提到的,它与LINQ To SQL的代码有关。
你必须看一下这个。在你的第一个例子中 - 如果我们看一下GetPeople将生成的表达式(即表达式树) - 用人类的话说它会生成一个树,指定我们从表中选择 - 然后在该表的每一行上应用MapToDomain函数碰巧返回DomainPerson类型的对象。
在第二个例子中,这次我们不仅知道返回类型是DomainPerson - 而且我们还能够看到哪些字段被映射到哪些属性(更重要的是如何)。这意味着,当您稍后运行Where和reference p.Quality时,Linq To SQL可以将其回溯到SQL表,并且知道DomainPerson.Quality映射到Persons表中的Quality列。
首先看起来有点奇怪,为什么第一个例子不起作用 - 但假设您的MapToDomain模型如此:
public void DomainPerson MapToDomain(Data.Person person){
return new DomainPerson {
Quality = person.Quality + " Quality";
//mode code here
};
}
现在LINQ To SQL应该如何知道这种“特殊”映射? - anwer很简单 - 它不能。
简而言之 - 当您在select语句中执行任何操作并且想要投影结果时,实际投影需要全部作为“内联”代码发生(我不确定其中的确切术语)您希望在此之后再进行查询(即排序,过滤等) - 否则查询引擎无法知道您的映射是如何工作的。
答案 3 :(得分:0)
反直觉可以翻译DomainPerson构造函数,而不能使用MapToDomain方法。
或许故事的内容多于显示的代码。这里的第二个例子中存在语法错误:
选择新的DomainPerson {
这实际上是代码中的匿名类型吗?