我有这样的POCO实体
public class Product : Entity
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
public virtual ICollection<Order> Orders { get; set; }
[NotMapped]
public int UsersCount
{
get
{
return Orders.Count();
}
}
}
产品访问方法
public IQueryable<Product> GetAll()
{
return _context.Product.Include(I=>I.Orders);
}
当我将所有产品加载到View
中时 var model = _productService.GetAll().Select(p => new AdminProductViewModel
{
Active = p.Active,
Id = p.Id,
Name = p.Name,
UsersCount = p.UsersCount
}).ToList();
我得到例外
LINQ to不支持指定的类型成员'UsersCount' 实体。
我真的无法理解为什么Linq to Entity会给出异常。也许有人解释了什么是错的?
我们还在其他应用程序中使用计算字段,如
public class User : Entity
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string Email { get; set; }
[MaxLength(50)]
public string FirstName { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public virtual ICollection<Statistic> Statistics { get; set; }
[NotMapped]
public bool Active
{
get
{
return Orders.Any(c => c.Active && (c.TransactionType == TransactionType.Order || c.TransactionType == TransactionType.Subscription));
}
}
[NotMapped]
public int CreditsLeft
{
get
{
return Orders.Where(w => w.Active).Sum(p => p.Credits != null ? p.Credits.Value : 0);
}
}
}
public User Get(int id)
{
return _context.User.FirstOrDefault(u => u.Id == id);
}
var user = _userService.Get(_authUser.Id);
var model = new UserViewModel
{
Active = user.Active,
FullName = user.FullName,
Email = user.Email,
};
并且没有任何问题,尽管EF6还有两个计算字段User.Active
和User.CreditsLeft
答案 0 :(得分:6)
请记住,LINQ to Entities尝试将每个LINQ语句转换为SQL。你的陈述......
var model = _productService.GetAll().Select(p => new AdminProductViewModel...
...是针对Select
(IQueryable
)的LINQ扩展方法(_productService.GetAll()
)。正如documentation所示,此方法将Expression
作为参数。
您可以将表达式视为一个令牌树,表达它应该执行的任务。简单地说,LINQ提供程序是表达语言中的标记字典&#34;在这种情况下,使用其他语言的标记,SQL。整个语句被翻译成SQL并由数据库执行。 .Net运行时只发送语句并处理返回的结果。
检查EF的源代码显示许多令牌是硬编码的:所有SQL关键字,一些内置(&#34;规范&#34;)函数(如DATEDIFF
)和精选的.Net方法。通过将实体属性映射到数据库列来添加其他标记。最近,ToString()
被添加到字典的.Net部分。在EF6中,我们可以写...
_context.Product.Select(p => p.Id.ToString())
在此之前,这会引起臭名昭着的
LINQ to Entities无法识别方法&#39; System.String ToString()&#39;
您的异常具有相同的原因,但它与成员而不是方法有关。 p.UsersCount
不在字典中,因为它没有映射。
我们还在其他应用程序中使用计算字段,如
此处已从数据库中提取User
并将其具体化为C#对象。现在,当您访问其属性时,它只运行.Net代码。这里没有SQL翻译。嗯......它可能触发延迟加载(订单和信用),但访问属性的行为不会发生在表达式的上下文中。
同样,您可以在获得UsersCount
个对象后访问Product
。如果您希望数据库对订单进行大量计算,那么您必须使用LINQ语句中的表达式:
var model = _productService.GetAll().Select(p => new AdminProductViewModel
{
Active = p.Active,
Id = p.Id,
Name = p.Name,
UsersCount = p.Orders.Count()
}).ToList();
答案 1 :(得分:0)
请改为尝试:
var model = _productService.GetAll().Select(p => new AdminProductViewModel
{
Active = p.Active,
Id = p.Id,
Name = p.Name,
UsersCount = p.Orders.Count()
}).ToList();
Linq to Entities无法将Product.UsersCount
属性转换为sql,因此它会向您显示错误消息
指定的类型成员&#39; UsersCount&#39; LINQ不支持 实体