呼吁内蒙古LINQ查询的异常当了ToList() [英] Exception on Inner LINQ query when calling ToList()

查看:157
本文介绍了呼吁内蒙古LINQ查询的异常当了ToList()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

昨天我工作的代码重构和跨我真的不能找到多少信息的异常来。这里的情况。

Yesterday I was working on a code refactor and came across an exception that I really couldn't find much information on. Here is the situation.

我们有一对具有多对多的关系通过关系表EF实体。有问题的对象,像这样,省去不必要的位。

We have an a pair of EF entities that have a many to many relationship through a relation table. The objects in question look like this, leaving out the unnecessary bits.

public partial class MasterCode
{
    public int MasterCodeId { get; set; }
    ...

    public virtual ICollection<MasterCodeToSubCode> MasterCodeToSubCodes { get; set; }
}

public partial class MasterCodeToSubCodes
{
    public int MasterCodeToSubCodeId { get; set; }
    public int MasterCodeId { get; set; }
    public int SubCodeId { get; set; }
    ...
}

现在,我试图运行一个LINQ查询针对这些实体。我们使用了很多LINQ预测到的DTO。该DTO和查询跟踪。 。masterCodeId是传入的参数

Now, I attempted to run a LINQ query against these entities. We use a lot of LINQ projections into DTOs. The DTO and the query follow. masterCodeId is a parameter passed in.

public class MasterCodeDto
{
    public int MasterCodeId { get; set; }
    ...

    public ICollection<int> SubCodeIds { get; set; }
}

(from m in MasterCodes
where m.MasterCodeId == masterCodeId
select new MasterCodeDto
{
    ...
    SubCodeIds = (from s in m.MasterCodeToSubCodes
                  select s.SubCodeId).ToList(),
    ...
}).SingleOrDefaultAsync();



内部查询抛出以下异常

The internal query throws the following exception

Expression of type 'System.Data.Entity.Infrastructure.ObjectReferenceEqualityComparer' cannot be used for constructor parameter of type 'System.Collections.Generic.IEqualityComparer`1[System.Int32]'

我们已经在我们的代码等地做过内部查询,这样并没有任何问题。在这其中的区别是,我们不是新ING了一个对象,并突出到它,而是返回一组,我们希望把在列表中的整数

We have done inner queries like this before in other places in our code and not had any issues. The difference in this one is that we aren't new-ing up an object and projecting into it but rather returning a group of ints that we want to put in a list.

我已经找到了解决方法通过改变IEnumerable的上MasterCodeDto ICollection中和丢弃了ToList(),但我从来没有能够找出为什么我不能只选择了IDS并返回它们作为一个列表。

I have found a workaround by changing the ICollection on MasterCodeDto to IEnumerable and dropping the ToList() but I was never able to find out why I couldn't just select the ids and return them as a list.

没有人有任何深入了解这个问题?当它不是一个内部查询的一部分,正常返回只是一个id字段,并调用了ToList()工作正常。我失去了对内部查询的限制,以防止这样的操作情况的发生?

Does anyone have any insight into this issue? Normally returning just an id field and calling ToList() works fine when it is not part of an inner query. Am I missing a restriction on inner queries that prevents an operation like this from happening?

感谢

编辑:为了让那里这种模式工作,我会告诉你一个示例例如,做工作的查询。

To give an example of where this pattern is working I'll show you an example of a query that does work.

 (from p in Persons
 where p.PersonId == personId
 select new PersonDto
 {
     ...
     ContactInformation = (from pc in p.PersonContacts
                           select new ContactInformationDto
                           {
                               ContactInformationId = pc.PatientContactId,
                               ...
                           }).ToList(),
     ...
  }).SingleOrDefaultAsync();

在这个例子中,我们选择到一个新的DTO,而不是仅仅选择一个值。它工作正常。该问题似乎只从选择一个值来阻止

In this example, we are selecting into a new Dto rather than just selecting a single value. It works fine. The issues seems to stem from just selecting a single value.

编辑2:在另一个有趣的扭曲,如果不是选择成MasterCodeDto我选择到一个匿名类型除外也没有到位用了ToList()抛出。

Edit 2: In another fun twist, if instead of selecting into a MasterCodeDto I select into an anonymous type the exception is also not thrown with ToList() in place.

推荐答案

我觉得你在实体框架中的错误绊倒了。 EF有选择适当的具​​体类型兑现收藏一些逻辑。 的HashSet< T> 是它的最爱之一。显然,(我不能完全跟着EF的源代码在这里),它选择的HashSet的ICollections和名单的IEnumerable

I think you stumbled upon a bug in Entity Framework. EF has some logic for picking an appropriate concrete type to materialize collections. HashSet<T> is one of its favorites. Apparently (I can't fully follow EF's source code here) it picks HashSet for ICollections and List for IEnumerable.

它看起来像EF试图通过使用创建的HashSet接受一个的IEqualityComparer< 构造; T> 。 (这发生在EF的 DelegateFactory 类,方法 GetNewExpressionForCollectionType )的错误是,它使用自己的 ObjectReferenceEqualityComparer 这一点。但是,这是一个的IEqualityComparer<对象> ,它不能被转换为的IEqualityComparer< INT方式>

It looks like EF tries to create a HashSet by using the constructor that accepts an IEqualityComparer<T>. (This happens in EF'sDelegateFactory class, method GetNewExpressionForCollectionType.) The error is that it uses its own ObjectReferenceEqualityComparer for this. But that's an IEqualityComparer<object>, which can not be converted to an IEqualityComparer<int>.

在总的来说,我认为这是最好的做法不使用了ToList 在LINQ查询和使用的IEnumerable 在DTO类型的集合。因此,EF将有完全的自由来挑选合适的具体类型。

In general I think it is best practice not to use ToList in LINQ queries and to use IEnumerable in collections in DTO types. Thus, EF will have total freedom to pick an appropriate concrete type.

这篇关于呼吁内蒙古LINQ查询的异常当了ToList()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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