在LINQ to Entities(EF4.1)中返回具有类型约束的generics的输入类型
我有一个简单的扩展方法,用于按标签过滤LINQ IQueryable。 我正在使用LINQ to Entities,接口为:
public interface ITaggable { ICollection Tags { get; } }
以下不起作用,返回IQueryable
而不是IQueryable
:
public static IQueryable WhereTagged(this IQueryable set, string tag) where T:ITaggable { return set.Where(s=>s.Tags.Any(t=>t.Name.ToLower() == tag.ToLower())); }
这导致LINQ to Entities强制转换exception:
“无法将类型’ReleaseGateway.Models.Product’转换为’ReleaseGateway.Models.ITaggable’.LINQ to Entities仅支持转换实体数据模型基元类型。” (System.NotSupportedException)捕获到System.NotSupportedException:“无法将类型’Project.Models.Product’强制转换为’Project.Models.ITaggable’.LINQ to Entities仅支持转换实体数据模型基元类型。”
它没有像这样的约束,但我必须在我的应用程序代码中显式声明类型T:
public static IQueryable WhereTagged(this IQueryable set, string tag) { return set.Where(s=>s.Tags.Any(t=>t.Name.ToLower() == tag.ToLower())).Cast(); }
问题:为什么类型约束会转换返回类型? 我可以重写这个来利用从扩展方法调用者推断类型吗?
我正在寻找相同的答案,并不满意所提供的答案的句法清洁度,我一直在寻找并发现这篇文章。
TL;博士; – 为你的约束添加类,它的工作原理 。
LINQ to Entities仅支持使用IEntity接口转换EDM原语或枚举类型
public static IQueryable WhereTagged (this IQueryable set, string tag) where T: class, ITaggable
我怀疑这个问题来自对s.Tags
的调用。 因为s
是一个Product
,但是你正在调用ITaggable.Tags
,生成的表达式看起来更像:
set.Where(s=>((ITaggable)s).Tags.Any(...))
这只会混淆entity framework。 试试这个:
((IQueryable)set) .Where(s=>s.Tags.Any(t=>t.Name.ToLower() == tag.ToLower())) .Cast();
由于IQueryable
是一个协变接口,因此将该集视为IQueryable
,这应该可以工作,因为您的第二个示例基本上完全相同。
dlev提到的最后你不需要那个Cast。
我假设产品类实现了ITaggable? 我认为删除Cast会解决问题。
你永远不会显示它的使用位置。 我认为你已经将IQueryable
首先传递给了方法。
概念certificatehttps://ideone.com/W8c66
using System; using System.Linq; using System.Collections.Generic; public class Program { public interface ITaggable {} public struct TagStruct : ITaggable {} public class TagObject : ITaggable {} public static IEnumerable DoSomething (IEnumerable input) where T: ITaggable { foreach (var i in input) yield return i; } public static void Main(string[] args) { var structs = new [] { new TagStruct() }; var objects = new [] { new TagObject() }; Console.WriteLine(DoSomething(structs).First().GetType()); Console.WriteLine(DoSomething(objects).First().GetType()); } }
产量
Program+TagStruct Program+TagObject
因此,它返回输入类型,而不是约束接口。
不足为奇,如果DoSometing需要两个接口,结果会是什么?
public static IEnumerable DoSomething (IEnumerable input) where T: ITaggable, ISerializable
??
上述就是C#学习教程:在LINQ to Entities(EF4.1)中返回具有类型约束的generics的输入类型分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/958854.html