Tom*_*mas 1 asp.net-mvc linq-to-entities entity-framework entity-framework-6.1
我有这样的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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
产品访问方法
public IQueryable<Product> GetAll()
{
return _context.Product.Include(I=>I.Orders);
}
Run Code Online (Sandbox Code Playgroud)
当我将所有产品加载到View中时
var model = _productService.GetAll().Select(p => new AdminProductViewModel
{
Active = p.Active,
Id = p.Id,
Name = p.Name,
UsersCount = p.UsersCount
}).ToList();
Run Code Online (Sandbox Code Playgroud)
我得到例外
LINQ to Entities不支持指定的类型成员'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,
};
Run Code Online (Sandbox Code Playgroud)
并且没有任何问题,EF6不会给出任何例外,尽管它也有两个计算字段User.Active和User.CreditsLeft
请记住,LINQ to Entities尝试将每个LINQ语句转换为SQL.你的陈述......
var model = _productService.GetAll().Select(p => new AdminProductViewModel...
Run Code Online (Sandbox Code Playgroud)
...是Select针对IQueryable(_productService.GetAll())的LINQ扩展方法().如文档所示,此方法采用Expressionas参数.
您可以将表达式视为表示应执行的任务的标记树.简单地说,LINQ提供程序是一个"表达式语言"中的令牌字典,用于其他语言的标记,在本例中为SQL.整个语句被翻译成SQL并由数据库执行..Net运行时只发送语句并处理返回的结果.
检查EF的源代码表明许多令牌都是硬编码的:所有SQL关键字,一些内置("规范")函数(如DATEDIFF)和一些.Net方法.通过将实体属性映射到数据库列来添加其他标记.最近,ToString()被添加到字典的.Net部分.在EF6中我们可以写...
_context.Product.Select(p => p.Id.ToString())
Run Code Online (Sandbox Code Playgroud)
在此之前,这会引起臭名昭着
LINQ to Entities无法识别方法'System.String ToString()'
您的异常具有相同的原因,但它与成员而不是方法有关.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();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6477 次 |
| 最近记录: |