我开始了这个问题 ,我有点回答有 ,现在我在这里问的更根本的问题。 我已经简化了查询到这一点:
var q = from ent in LinqUtils.GetTable<Entity>()
from tel in ent.Telephones.DefaultIfEmpty()
select new {
Name = ent.FormattedName,
Tel = tel != null ? tel.FormattedNumber : "" // this is what causes the error
};
tel.FormattedNumber
是结合了一个属性Number
和Extension
领域成整齐的格式化字符串。 下面是导致错误:
System.InvalidOperationException: Could not translate expression 'Table(Entity).SelectMany(ent => ent.Telephones.DefaultIfEmpty(), (ent, tel) => new <>f__AnonymousType0`2(Name = ent.FormattedName, Tel = IIF((tel != null), tel.FormattedNumber, "")))' into SQL and could not treat it as a local expression.
如果我从改变高于参考FormattedNumber
只是普通的Number
,一切工作正常。
但我想格式化的数字在我的名单上完美呈现。 你有什么建议的最巧妙的,这样做的最彻底的方法?
你可以使用AsEnumerable
的实体,但是这将迫使它带回所有列(即使不使用); 或许反而是这样的:
var q1 = from ent in LinqUtils.GetTable<Entity>()
from tel in ent.Telephones.DefaultIfEmpty()
select new {
Name = ent.FormattedName,
Number = (tel == null ? null : ent.Number),
Extension = (tel == null ? null : ent.Extension)
};
var q2 = from row in q1.AsEnumerable()
select new {
row.Name,
FormattedNumber = FormatNumber(row.Number, row.Extension)
};
其中FormatNumber
是一些方法,它采用了两个合并它们,想必从其他(财产)的代码重新使用。
随着LINQ到SQL,另一种选择是揭露一个UDF上,做数据库内的数据格式化上下文; 一个稍微不同的实施例:
var qry = from cust in ctx.Customers // and tel
select new {
cust.Name,
FormattedNumber = ctx.FormatNumber(tel.Number, tel.Extension)
};
(这将做的工作,在数据库中;而不论这是否是一个好主意;-p)
清洁的方法是说明你其实想表达的领域,把它们放在中间层的对象,然后使用任何辅助功能对其进行修改后者。
我不知道你是否意识到,对LINQ一类代表SQL表是一个DTO类 - 它定义了LINQ-SQL翻译使用的语法。 注入一个属性,不映射到SQL表中的DTO甚至不支持 - 这意味着翻译可以开火的意志。 属性定义的语法和任何不被他们定义为表达翻译不存在。
在FROM子句中命名实体不是对象 - 它们是用来帮助阐明,这将是获取实际的表中的字段只是符号。 没有选择明确指定一个字段是不是牵强 - 至少这是译者的目标,它可能通过让滑数。 例如,如果是ent.FormattedName没有声明,这是一个滑可能会发生爆炸后者。
因此,注入到DTO类FormattedNumber财产甚至没有在语法中存在。 这不是一个“计算的领域” - 这个词是严格的SQL表定义,如果你有一个它会在DTO的语法。 请注意,错误说非常精确地“地方表达” - 范围非常有限。
您可以尝试通过嵌套lambda表达式在整个“电话”,它可能通过靶向整个记录的获取调用静态函数欺骗 - 或者抛出另外的异常。
其他LINQ-S,这是不是翻译,可以有放宽的规定。 LINQ-SQL,必须为很严格,非常缓慢的,它已经够慢:-)
@Marc Gravell打我的答案,信贷也以各种应答者对这个问题谁把我在正确的轨道上。
我做到了,就像马克的第一个建议,像这样:
var q1 = from ent in LinqUtils.GetTable<Entity>()
from tel in ent.Telephones.DefaultIfEmpty()
select new { ent, tel };
var q2 = from q in q1.AsEnumerable()
select new {
Name = q.ent.FormattedName,
Tel = q.tel != null ? q.tel.FormattedNumber : ""
};
而且做到了! 谢谢大家!
文章来源: Linq “Could not translate expression… into SQL and could not treat it as a local expression.”