强制转换为IQueryable类型以在Linq中连接到实体

编程入门 行业动态 更新时间:2024-10-27 20:34:47
本文介绍了强制转换为IQueryable类型以在Linq中连接到实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我的通用类中有以下方法:

I have the following method in my generic class:

// This is the class declaration public abstract class BaseService<TEntity, TKey> : IBaseService<TEntity, TKey> where TEntity : class, IEntity<TKey> // The Method public IQueryable<TEntity> GetActive() { if (typeof(IActivable).IsAssignableFrom(typeof(TEntity))) { return this.repository.Get().Cast<IActivable>() .Where(q => q.Active) .Cast<TEntity>(); } else { return this.Get(); } }

这是界面:

public interface IActivable { bool Active { get; set; } }

基本上,TEntity是一个实体(POCO)类,如果它们具有Active属性,则可以实现IActivable.我想要该方法返回所有Active值为true的记录.但是,我有此错误:

Basically, TEntity is an Entity (POCO) class, that can implement IActivable if they have Active property. I want to the method to return all records that have Active value true. However, I have this error:

无法将类型"WebTest.Models.Entities.Product"转换为类型 'Data.IActivable'. LINQ to Entities仅支持投射EDM 基本或枚举类型.

Unable to cast the type 'WebTest.Models.Entities.Product' to type 'Data.IActivable'. LINQ to Entities only supports casting EDM primitive or enumeration types.

我了解为什么会发生此错误.但是关于SO的文章没有针对我的情况的任何有效解决方案. Cast或其他方法可以实现吗?注意:我不想转换为IEnumerable,我想保留IQueryable.

I understand why this error occurs. But the articles on SO does not have any valid solution for my case. Is it achievable with Cast, or any other way? Note: I do not want to convert to IEnumerable, I want to keep IQueryable.

推荐答案

EF表达式解析器无需强制转换即可工作,但是如果不进行强制转换,您将无法编译C#代码(C#会抱怨它不能知道TEntity具有Active属性).解决方案是:对c#编译器进行强制转换,而不对EF表达式解析器进行强制转换.

The EF expression parser will work without casting, however you won't be able to compile the C# code without the casting (C# will complain that it doesn't know that TEntity has an Active property). The solution is: cast for the c# compiler and not cast for the EF expression parser.

因此,如果确定(正在if中对其进行检查)该对象实现了IActivable,则可以使用转换(用于编译)创建表达式,然后在运行时删除转换(这是不必要的)对于EF.对于您的特定情况:

So if you are sure (you are checking it in the if, so you are) that the object implements IActivable, you can create the expression with the casting (for compiling) and then remove the castings in runtime (which are unnecessary) for EF. For your particular case:

public IQueryable<TEntity> GetActive() { if (typeof(IActivable).IsAssignableFrom(typeof(TEntity))) { Expression<Func<TEntity, bool>> getActive = x => ((IActivable)x).Active; getActive = (Expression<Func<TEntity, bool>>)RemoveCastsVisitor.Visit(getActive); return this.repository.Get().Where(getActive); } else { return this.Get(); } }

表达式访问者是这样实现的:

The expression visitor is implemented like this:

internal class RemoveCastsVisitor : ExpressionVisitor { private static readonly ExpressionVisitor Default = new RemoveCastsVisitor(); private RemoveCastsVisitor() { } public new static Expression Visit(Expression node) { return Default.Visit(node); } protected override Expression VisitUnary(UnaryExpression node) { if (node.NodeType == ExpressionType.Convert && node.Type.IsAssignableFrom(node.Operand.Type)) { return base.Visit(node.Operand); } return base.VisitUnary(node); } }

它只是检查是否需要强制类型转换:如果实际值已经实现了强制类型转换,它只会从表达式中删除转换,EF会正确地选择它.

It just checks if a casting is necessary: if the actual value already implements the type it's casting to, it'll just remove the conversion from the expression, and EF will pick it up correctly.

更多推荐

强制转换为IQueryable类型以在Linq中连接到实体

本文发布于:2023-10-26 11:09:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1529959.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:转换为   连接到   实体   类型   IQueryable

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!