C#EF Linq如何写代码利用分类ID获取分类名称?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#EF Linq如何写代码利用分类ID获取分类名称?相关的知识,希望对你有一定的参考价值。

var list = WebProductService.GetListByPage(queries.AsExpression<WebProduct>(), x => true, pageInfo.Limit, pageInfo.Page, out int totalCount, true).Select(x => new x.Id, x.ProductName, x.IsShow, x.IsHot, x.ImgUrl, x.CategoryId, x.WebProductCategory.CategoryName, x.SortCode ).OrderBy(x => x.SortCode).ToList(); return Json(Pager.Paging(list, totalCount), JsonRequestBehavior.AllowGet);项目产品列表里面存着产品分类ID,查询列表的时候需要获取产品分类名称,尝试了好多写法也不会写linq的left join,求大神指点。谢谢

参考技术A 看你这个写法是封装的方法,而且实体里面其实已经有了分类对象(导航属性)了,所以按我理解不需要什么left join去连接两个表。不知道这样说你是否明白。

EF + LINQ:如何定义和利用变量(可能是 Func 变量)来定义 Select 语句的一部分?

【中文标题】EF + LINQ:如何定义和利用变量(可能是 Func 变量)来定义 Select 语句的一部分?【英文标题】:EF + LINQ: How do I define and utilize a variable (maybe a Func variable) to define part of a Select statement? 【发布时间】:2018-01-15 08:36:59 【问题描述】:

在尝试使用变量之前(这有 sql server 进行计算):

IQueryable<MyEntity> query = _dbSet; // IQueryable<TEntity>
var results = query.Select(m => new MyViewModel

    MyCalculation = m.Column1 * m.Column2
).ToList();

我想要做什么(从 Func 变量或其他类型的变量动态创建我的 select 语句的一部分以允许这样做):

IQueryable<MyEntity> query = _dbSet; // IQueryable<TEntity>
Func<MyEntity, decimal> funcVariableAttempt = m => m.Column1 * m.Column2;
var results = query.Select(m => new MyViewModel

    MyCalculation = funcVariableAttempt.Invoke(m) // My foolish attempt does not work.
).ToList();

当我尝试我想要的东西时遇到的错误(也就是我的愚蠢尝试):

LINQ to Entities 无法识别方法 'System.Decimal Invoke(MyProject.Repository.Models.MyEntity)' 方法,并且该方法无法转换为存储表达式。

如何定义和利用变量(可能是 Func 变量)来定义 Select 语句的一部分?

【问题讨论】:

你不能使用Func,它不能传递给SQL层。 参见this answer 和库LinqKit,可用于在IQueryable 中嵌入Expression&lt;Func&lt;...&gt;&gt; 【参考方案1】:

这是我之前偶然发现的一个完全有效的问题,并找到了一个适合我的解决方案。

Func&lt;MyEntity, decimal&gt; 的问题在于它是一个委托,并且 O/R 映射器必须有权访问内部表达式(在您的情况下是两个属性的乘法)。但是这些信息会被编译到委托中并永远隐藏。

但是,如果您从 Expression&lt;Func&lt;MyEntity, decimal&gt;&gt; customCalculation 开始,事情看起来更有希望,因为您将内部逻辑作为表达式树。 问题在于:您不能调用表达式。 customCalculation(m) 无法编译。

编译器会让你写

m => new MyViewModel  MyCalculation = customCalculation.Compile()(m) 

,但大多数 O/R 映射器无法理解这一点。

但你看到它至少以某种方式包含customCalculation lambda 表达式,以及它与周围表达式的关系。

从这里到原始工作版本中的表达式树涉及一些表达式操作:

我们必须将 customCalculation.Compile()(m) 替换为要成为 Compile()d 的 lambda 的 body,但将 lambda 的参数替换为委托调用。因此,如果customCalculationx =&gt; x.Column1 * x.Column2,则必须将customCalculation.Compile()(m) 替换为m.Column1 * m.Column2

这样做并非易事,因为 lambda 本身必须从编译器生成的闭包类实例内的字段中挖掘出来。

我已经发布了这个表达式操纵器 in another similar question 的实现。希望对您有所帮助。

有了它,你应该能够:

var customCalculation = (Expression<Func<MyEntity, decimal>>)(x => x.Column1 * x.Column2);
var selector = Express.Prepare((Expression<Func<MyEntity, MyViewModel>>)(m => new MyViewModel  MyCalculation = customCalculation.Compile()(m) ));
var result = query.Select(selector).ToList();

【讨论】:

仅供参考:我认为这是迄今为止最好的答案!太感谢了。您实际上在这里让我有些困惑,但是结合您指向类似问题的链接,我能够实现我的目标!再次感谢! 很高兴我能帮上忙。诚然,我在解释事情方面做得不好。编辑了答案,希望让它更容易理解。【参考方案2】:

如您所知,您的 funcVariableAttempt 对您的数据库没有意义,因此您必须在 linq-to-object 上下文中调用您的方法。例如,首先以Enumerable 的形式获取数据,然后调用您的方法:

var results = query.Select(m => new 
Column1= col1,
Column2= col2
).AsEnumerable()
    .Select(m => new MyViewModel

    MyCalculation = Foo(m.Column1, m.Column2)
);

*注意:代码未经测试。

【讨论】:

【参考方案3】:

您应该首先调用 ToList() 并对内存中的结果执行 Select()。

var results = query.ToList() 
 .Select(m => new MyViewModel  
    MyCalculation = Foo(m.Column1, m.Column2)
 );

您正在尝试将 Select 作为查询的一部分执行。您应该只使用常规函数进行映射计算。 Lambda 函数对 LINQ 很有用,但在这种情况下不需要它们。

【讨论】:

提示:在这种情况下使用AsEnumerable() 而不是ToList()。你不想要一个列表,你只想欺骗编译器重载解析Select 的IEnumerable 版本。另外我认为问题是关于如何将 MyCalculation 表达式放入 .Select 选择器中以由 EF 转换为 SQL。

以上是关于C#EF Linq如何写代码利用分类ID获取分类名称?的主要内容,如果未能解决你的问题,请参考以下文章

LINQ To EF

连续获取最大值时如何解决错误(EF Core Linq)? [复制]

EF查询 linq写法 DbContext.DbSet<TEntity>

利用LinQ技术和lambd表达式进行增删改查

laravel关于产品分类的说说说

destoon的二级分类名调用怎么写?