指定的类型成员' UsersCount' LINQ to Entities不支持

时间:2014-09-16 11:23:30

标签: asp.net-mvc entity-framework linq-to-entities 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(); 
            }
        }

}

产品访问方法

 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.ActiveUser.CreditsLeft

,但它没有任何例外

2 个答案:

答案 0 :(得分:6)

请记住,LINQ to Entities尝试将每个LINQ语句转换为SQL。你的陈述......

var model = _productService.GetAll().Select(p => new AdminProductViewModel...

...是针对SelectIQueryable)的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不支持   实体