Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将LINQ中带有类型约束的泛型输入类型返回给实体(EF4.1)_C#_Linq_Generics_Linq To Entities - Fatal编程技术网

C# 将LINQ中带有类型约束的泛型输入类型返回给实体(EF4.1)

C# 将LINQ中带有类型约束的泛型输入类型返回给实体(EF4.1),c#,linq,generics,linq-to-entities,C#,Linq,Generics,Linq To Entities,我有一个简单的扩展方法,可以通过标记过滤LINQ IQueryable。我将其用于LINQ to实体,接口为: public interface ITaggable { ICollection<Tag> Tags { get; } } 公共接口ITaggable { ICollection标记{get;} } 以下操作不起作用,返回的是IQueryable,而不是IQueryable: publicstaticiqueryable wheretaged(此IQuerya

我有一个简单的扩展方法,可以通过标记过滤LINQ IQueryable。我将其用于LINQ to实体,接口为:

public interface ITaggable
{
    ICollection<Tag> Tags { get; } 
}
公共接口ITaggable
{
ICollection标记{get;}
}
以下操作不起作用,返回的是
IQueryable
,而不是
IQueryable

publicstaticiqueryable wheretaged(此IQueryable集合,字符串标记),其中T:ITaggable
{
返回set.Where(s=>s.Tags.Any(t=>t.Name.ToLower()==tag.ToLower());
}
这将导致LINQ到实体强制转换异常:

无法将类型“ReleaseGateway.Models.Product”强制转换为类型 “ReleaseGateway.Models.ITaggable”。LINQ to实体仅支持 转换实体数据模型基元类型。“ (System.NotSupportedException)创建了System.NotSupportedException 捕获:“无法将类型“Project.Models.Product”强制转换为类型 “Project.Models.ITaggable”。LINQ to实体仅支持强制转换 实体数据模型基元类型。“

它可以在没有如下约束的情况下工作,但我必须在应用程序代码中显式声明T类型:

public static IQueryable<T> WhereTagged<T>(this IQueryable<ITaggable> set, string tag)
{
    return set.Where(s=>s.Tags.Any(t=>t.Name.ToLower() == tag.ToLower())).Cast<T>();
}
publicstaticiqueryable-wheretaged(此IQueryable集,字符串标记)
{
返回set.Where(s=>s.Tags.Any(t=>t.Name.ToLower()==tag.ToLower()).Cast();
}

问题:为什么类型约束强制转换返回类型?我可以重写它以利用从扩展方法调用方推断的类型吗?

您永远不会显示在哪里使用它。我认为您首先已经在向该方法传递一个
IQueryable

概念证明

因此,它返回的是输入类型,而不是受约束的接口

毫不奇怪,如果剂量测量需要两个接口,结果会怎样

    public static IEnumerable<T> DoSomething<T>(IEnumerable<T> input) 
        where T: ITaggable, ISerializable
公共静态IEnumerable剂量仪(IEnumerable输入)
其中T:Itagable,ISerializable

你不需要像德莱夫所说的那样在结尾处施展石膏


我假设product类实现了ITaggable?我认为删除强制转换将解决问题。

我怀疑问题是由调用
s.Tags
引起的。由于
s
产品
,但您正在调用
ITaggable.Tags
,因此生成的表达式更像:

set.Where(s=>((ITaggable)s).Tags.Any(...))
这只是混淆了实体框架。试试这个:

((IQueryable<ITaggable>)set)
    .Where(s=>s.Tags.Any(t=>t.Name.ToLower() == tag.ToLower()))
    .Cast<T>();
((IQueryable)集)
.Where(s=>s.Tags.Any(t=>t.Name.ToLower()==tag.ToLower())
.Cast();

由于
IQueryable
是一个协变接口,这将把集合视为一个
IQueryable
,因为您的第二个示例基本上做了相同的事情。我正在寻找相同的答案,但对所提供答案的语法清晰性不满意,我一直在找,找到了这篇文章

tl;博士;-将类添加到约束中,它就可以工作了

publicstaticiqueryable-wheretaged(此IQueryable集,字符串标记)
其中T:类,它是可聚合的

例如,这用于db.Products.wheretaged(“NonQuarterlyRelease”),其中db是一个DbContext,Products是一个DbSetI。我很确定您会发现
wheretaged
返回
IQueryable
…是的。它可以很好地处理LINQ到对象,但会中断LINQ到实体。我明白了。对不起,那不在我的管辖范围之内。如果它能以不同的方式工作,我会非常感兴趣。我猜不应该。不管怎样,大多数curious@StriplingWarrior:你说得对,在第一个示例中.Cast是多余的。我会编辑的。但例外情况是一样的。我认为它特别与LINQ to Entities有关。您使用的是什么版本的Entity Framework?我使用的是EF 4.1,首先是代码。演员阵容是多余的,我已经编辑掉了。不过,我还是收到了同样的例外。谢谢——这很有效!可能想编辑此答案以供其他人参考。@Jasonenizac:看起来更好吗?是的,再次感谢您的帮助。非常感谢!这才使我免于头痛!:-)谢谢,伙计,非常简单和聪明。我为一个类似的问题浪费了几乎一天的时间。
    public static IEnumerable<T> DoSomething<T>(IEnumerable<T> input) 
        where T: ITaggable, ISerializable
set.Where(s=>((ITaggable)s).Tags.Any(...))
((IQueryable<ITaggable>)set)
    .Where(s=>s.Tags.Any(t=>t.Name.ToLower() == tag.ToLower()))
    .Cast<T>();
public static IQueryable<T> WhereTagged<T>(this IQueryable<T> set, string tag)
    where T: class, ITaggable