指定的类型成员“UsersCount'不是在LINQ支持实体 [英] The specified type member 'UsersCount' is not supported in LINQ to Entities

查看:98
本文介绍了指定的类型成员“UsersCount'不是在LINQ支持实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的POCO实体

 公共类产品:实体 {
        [DatabaseGenerated(DatabaseGeneratedOption.None)
        公众诠释标识{搞定;组; }
        [需要]
        [MAXLENGTH(50)]
        公共字符串名称{;组; }
        公共虚拟的ICollection<排序>订单{搞定;组; }        [NotMapped]
        公众诠释UsersCount
        {
            得到
            {
                返回Orders.Count();
            }
        }}

产品访问方式

 公开的IQueryable<产品与GT;得到所有()
        {
            返回_context.Product.Include(I => I.Orders);
        }

在我所有的产品加载到浏览

  VAR模型= _productService.GetAll()选择(P =方式>新AdminProductViewModel
        {
            活动= p.Active,
            ID = p.Id,
            名称= p.Name,
            UsersCount = p.UsersCount
        })了ToList()。

我得到异常


  

指定的类型成员UsersCount'不是在LINQ支持
  实体。


我真的不明白,为什么LINQ到实体给予例外。也许有人解释什么是错的?

我们还可以使用计算字段在另一个这样的应用程序

 公共类用户:实体
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)
        公众诠释标识{搞定;组; }
        [需要]
        [MAXLENGTH(50)]
        公共字符串电子邮件{获得;组; }
        [MAXLENGTH(50)]
        公共字符串名字{获得;组; }
        [MAXLENGTH(50)]
        公共字符串名字{获得;组; }        公共虚拟的ICollection<排序>订单{搞定;组; }
        公共虚拟的ICollection<&统计GT;统计{搞定;组; }        [NotMapped]
        公共BOOL活动
        {
            得到
            {
                返回Orders.Any(C => c.Active&放大器;及(c.TransactionType == TransactionType.Order || c.TransactionType == TransactionType.Subscription));
            }
        }        [NotMapped]
        公众诠释CreditsLeft
        {
            得到
            {
                返回Orders.Where(W => w.Active).SUM(P => p.Credits = NULL p.Credits.Value:?0);
            }
        }
}    公众获取用户(INT ID)
    {
        返回_context.User.FirstOrDefault(U => u.Id == ID);
    }VAR用户= _userService.Get(_authUser.Id); VAR模型=新UserViewModel
            {
                活动= user.Active,
                全名= user.FullName,
                电子邮件= user.Email,
            };

和没有问题,EF6不给任何异常,虽然它也有两个计算字段 User.Active User.CreditsLeft


解决方案

记住,LINQ到实体尝试将每个LINQ语句转换成SQL。你的声明...

  VAR模型= _productService.GetAll()选择(P =方式>新AdminProductViewModel ...

...是一个LINQ扩展方法(选择)针对的IQueryable _productService.GetAll())。由于文档表明,该方法采用防爆pression 作为参数。<​​/ p>

您可以看到一个前pression作为树的标记前preSS 的任务就应该执行。一个LINQ提供程序,只是简单地说,就是在这种情况下,前pression语言来标记在其他一些语言,SQL令牌的字典。整个语句转换成SQL和数据库执行。 .NET运行时只发送声明路程,处理返回的结果。

检查EF的源$ C ​​$ C发现,很多标记是硬codeD:所有SQL关键字,一些内置(规范)的功能(如 DATEDIFF ),并选择.NET方法。其他令牌通过映射实体属性添加到数据库列。近日,的ToString()添加到字典的净一部分。在EF6我们可以这样写...

  _context.Product.Select(P =&GT; p.Id.ToString())

这之前,这将提高声名狼藉的


  

LINQ到实体无​​法识别方法'System.String的ToString()


您的异常有相同的原因,但它涉及到的方法代替成员。 p.UsersCount 没有在字典里,因为它没有被映射。


  

我们还可以使用计算字段在另一个这样的应用程序


下面一个用户已经从数据库中读取和物化为C#对象。现在,当您访问其属性,它只是净code运行。有没有SQL翻译怎么回事。嗯...它可能触发延迟加载(订单和学分),但行为的访问的属性并不在离pression的背景下发生的。

同样,您也可以访问 UsersCount 一旦你已经有了一个产品对象。如果你希望数据库做计算订单的繁重,你将不得不使用ex pression在LINQ语句:

  VAR模型= _productService.GetAll()选择(P =方式&gt;新AdminProductViewModel
    {
        活动= p.Active,
        ID = p.Id,
        名称= p.Name,
        UsersCount = p.Orders.Count()
    })了ToList()。

I have such POCO entity

  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(); 
            }
        }

}

Product access method

 public IQueryable<Product> GetAll()
        {
            return _context.Product.Include(I=>I.Orders);          
        }    

When I load all products into View

      var model = _productService.GetAll().Select(p => new AdminProductViewModel
        {
            Active = p.Active,
            Id = p.Id,
            Name = p.Name,
            UsersCount = p.UsersCount
        }).ToList();

I get exception

The specified type member 'UsersCount' is not supported in LINQ to Entities.

I really can't understand why Linq to Entity gives exception. Maybe someone explain what is wrong?

We also use calculated fields in another application like this

 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,
            };

and have no problems, EF6 don't give any exception though it also has two calculated fields User.Active and User.CreditsLeft

解决方案

Keep in mind that LINQ to Entities tries to translate each LINQ statement into SQL. Your statement...

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

...is a LINQ extension method (Select) against an IQueryable (_productService.GetAll()). As the documentation shows, this method takes an Expression as argument.

You can see an expression as a tree of tokens that express the task it should execute. A LINQ provider, simply said, is a dictionary of tokens in "expression language" to tokens in some other language, SQL in this case. The whole statement is translated into SQL and executed by the database. The .Net runtime only sends the statement away and processes the returned result.

Inspecting EF's source code reveals that many tokens are hard-coded: all SQL keywords, a number of built-in ("canonical") functions (like DATEDIFF) and a selection of .Net methods. Other tokens are added by mapping entity properties to database columns. Recently, ToString() was added to the .Net part of the dictionary. In EF6 we can write...

_context.Product.Select(p => p.Id.ToString())

Before that, this would raise the infamous

LINQ to Entities does not recognize the method 'System.String ToString()'

Your exception has the same cause, but it pertains to members in stead of methods. p.UsersCount is not in the dictionary because it is not mapped.

We also use calculated fields in another application like this

Here a User has been fetched from the database and materialized as a C# object. Now when you access its properties it's just .Net code running. There's no SQL translation going on here. Well... it probably triggers lazy loading (of orders and credits), but the act of accessing the property does not happen in the context of an expression.

Likewise, you can access UsersCount once you've got a Product object. If you want the database to do the heavy lifting of counting the orders, you'll have to use the expression in the LINQ statement:

var model = _productService.GetAll().Select(p => new AdminProductViewModel
    {
        Active = p.Active,
        Id = p.Id,
        Name = p.Name,
        UsersCount = p.Orders.Count()
    }).ToList();

这篇关于指定的类型成员“UsersCount'不是在LINQ支持实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆