我遇到了LINQ to SQL的一些特性。
使用相对简单的查询,我想选择一些字段,但是将日期字段格式化为字符串,我首先这样做:
var list = dataContext.MyLists.Single(x => x.ID == myId);
var items = from i in list.MyItems
select
new
{
i.ID,
i.Sector,
i.Description,
CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "",
DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : ""
};
后来我尝试了以下查询,这是完全相同的,除了我直接从我的dataContext查询,而不是我的第一个查询中的一个元素:
var items = from i in dataContext.MyLists
select
new
{
i.ID,
i.Sector,
i.Description,
CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "",
DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : ""
};
第一个运行正常,但第二个查询产生:
无法将表达式“...”转换为SQL,并且无法将其视为本地表达式。
如果我删除格式化日期的行,它可以正常工作。如果我删除.HasValue检查它也可以正常工作,直到有空值。
有什么想法吗?
安东尼
答案 0 :(得分:14)
我在不进行格式化的情况下执行SQL部分,然后在客户端进行格式化:
var items = list.MyItems.Select(item => new { item.ID, item.Sector, item.Description,
item.CompleteDate, item.DueDate })
.AsEnumerable() // Don't do the next bit in the DB
.Select(item => new { item.ID, item.Sector, item.Description,
CompleteDate = FormatDate(CompleteDate),
DueDate = FormatDate(DueDate) });
static string FormatDate(DateTime? date)
{
return date.HasValue ? date.Value.ToShortDateString() : ""
}
答案 1 :(得分:8)
在第一个查询中,到第二行运行时,您已经从数据库中获取了数据(var items = ...)。这意味着第二行在客户端运行,ToShortDateString可以非常愉快地运行。
在第二个查询中,因为select直接在IQueryable集合(dataContext.MyLists)上运行,所以它会尝试将select转换为SQL以便在服务器上进行处理,其中ToShortDateString不被理解 - 因此“无法翻译”。 “例外。
为了更好地理解这一点,你真的需要理解IQueryable和IEnumerable之间的区别,并且此时Linq To Sql查询将停止IQueryable并变为IEnumerable。网上有很多关于此事的内容。
希望这有帮助,
保
答案 2 :(得分:6)
就像错误消息告诉您的那样,区别在于连接到SQL时本地可以远程执行的操作。
Linq代码必须由Linq转换为SQL转换为远程数据提取的SQL命令 - 不能包含任何必须在本地完成的操作。
一旦你将它拉入本地对象(在第一个例子中),它就不再使用Linq to SQL了,只是普通的Linq。那时你可以自由地对它进行局部操作。
答案 3 :(得分:2)
您的样本中可能存在复制和粘贴错误或只是拼写错误。但如果没有,这可能就是问题......
在第二个查询中,您正在查询列表集合,而在第一个查询中,您正在查询列表中的项目。但是您没有调整查询以解释这种差异。
你需要的可能是这个。请注意第二个样本中没有出现的注释行。
var items = from aList in dataContext.MyLists
from i in aList.MyItems // Access the items in a list
where aList.ID == myId // Use only the single desired list
select
new
{
i.ID,
i.Sector,
i.Description,
CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "",
DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : ""
};
答案 4 :(得分:1)
ToShortDateString()