Ano*_*use 80 linq linq-to-entities entity-framework
我有这个linq查询:
private void GetReceivedInvoiceTasks(User user, List<Task> tasks)
{
var areaIds = user.Areas.Select(x => x.AreaId).ToArray();
var taskList = from i in _db.Invoices
join a in _db.Areas on i.AreaId equals a.AreaId
where i.Status == InvoiceStatuses.Received && areaIds.Contains(a.AreaId)
select new Task {
LinkText = string.Format(Invoice {0} has been received from {1}, i.InvoiceNumber, i.Organisation.Name),
Link = Views.Edit
};
}
Run Code Online (Sandbox Code Playgroud)
它有问题.我正在尝试创建任务.对于每个新任务,当我将链接文本设置为像"Hello"这样的常量字符串时,它很好.但是上面我试图使用发票的属性来构建属性linktext.
我收到此错误:
base {System.SystemException} = {"LINQ to Entities无法识别方法'System.String Format(System.String,System.Object,System.Object)'方法,并且此方法无法转换为商店表达式." }
谁知道为什么?有人知道这样做的另一种方法是让它起作用吗?
Bro*_*ass 140
实体框架试图在SQL端执行您的投影,其中没有相应的string.Format.使用AsEnumerable()给力的那部分的评价使用LINQ到对象.
基于我之前给出的答案,我将重构您的查询,如下所示:
int statusReceived = (int)InvoiceStatuses.Received;
var areaIds = user.Areas.Select(x=> x.AreaId).ToArray();
var taskList = (from i in _db.Invoices
where i.Status == statusReceived && areaIds.Contains(i.AreaId)
select i)
.AsEnumerable()
.Select( x => new Task()
{
LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.Organisation.Name),
Link = Views.Edit
});
Run Code Online (Sandbox Code Playgroud)
此外,我看到您在查询中使用相关实体(Organisation.Name)确保您在查询中添加适当的实体Include,或者具体实现这些属性以供以后使用,即:
var taskList = (from i in _db.Invoices
where i.Status == statusReceived && areaIds.Contains(i.AreaId)
select new { i.InvoiceNumber, OrganisationName = i.Organisation.Name})
.AsEnumerable()
.Select( x => new Task()
{
LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.OrganisationName),
Link = Views.Edit
});
Run Code Online (Sandbox Code Playgroud)
Nik*_*lay 15
IQueryable源自IEnumerable,主要的相似之处在于,当您进行查询时,它以其语言发布到数据库引擎,您可以告诉C#处理服务器(不是客户端)上的数据或告诉SQL处理数据数据.
所以基本上当你说IEnumerable.ToString(),C#获取数据集合并调用ToString()对象.但是当你说IQueryable.ToString()C#告诉SQL调用ToString()该对象但SQL中没有这样的方法时.
缺点是当您在C#中处理数据时,在C#应用过滤器之前,必须在内存中构建您正在查看的整个集合.
最有效的方法是使查询IQueryable与您可以应用的所有过滤器一样.
然后在内存中构建它并在C#中进行数据格式化.
IQueryable<Customer> dataQuery = Customers.Where(c => c.ID < 100 && c.ZIP == 12345 && c.Name == "John Doe");
var inMemCollection = dataQuery.AsEnumerable().Select(c => new
{
c.ID
c.Name,
c.ZIP,
c.DateRegisterred.ToString("dd,MMM,yyyy")
});
Run Code Online (Sandbox Code Playgroud)
虽然 SQL 不知道如何处理 a,string.Format但它可以执行字符串连接。
如果运行以下代码,那么您应该获得所需的数据。
var taskList = from i in _db.Invoices
join a in _db.Areas on i.AreaId equals a.AreaId
where i.Status == InvoiceStatuses.Received && areaIds.Contains(a.AreaId)
select new Task {
LinkText = "Invoice " + i.InvoiceNumber + "has been received from " + i.Organisation.Name),
Link = Views.Edit
};
Run Code Online (Sandbox Code Playgroud)
一旦您实际执行查询,这应该比使用稍微快一些AsEnumerable(至少这是我在出现与您相同的原始错误后在自己的代码中发现的)。如果您正在使用 C# 做一些更复杂的事情,那么您仍然需要使用AsEnumerable。
| 归档时间: |
|
| 查看次数: |
87324 次 |
| 最近记录: |