实体框架核心的AddRangeAsync()在通用方法中不起作用

时间:2019-04-23 19:39:34

标签: entity-framework entity-framework-core

这有效:

await AddRangeAsync(myEntities);

但这不起作用:

await AddEntities(myEntities);

...当我尝试使用此功能时:

private async Task AddEntities<T>(IEnumerable<T> entities)
{
    await AddRangeAsync(entities);
}

我收到一个错误:"The entity type 'List<MyType>' was not found. Ensure that the entity type has been added to the model."

这是我正在做的更大的抽象工作的一部分。为什么会出现此错误以及如何解决?

1 个答案:

答案 0 :(得分:2)

这是params object[]陷阱的另一个示例。

AddRangeAsync有两个重载:

(1)

Task AddRangeAsync(IEnumerable<object> entities, CancellationToken cancellationToken = default)

(2)

Task AddRangeAsync(params object[] entities)

我假设您想调用(1),但问题是-实际在这里调用哪个:

private async Task AddEntities<T>(IEnumerable<T> entities)
{
    await AddRangeAsync(entities);
}

答案是-这取决于!

如果Tclass约束,它将调用(1),否则调用(2)。这是因为IEnumerable<T>仅对引用类型是协变的,因此仅当编译器知道IEnumerable<object>是引用类型时才可以将其视为T,这是通过class约束实现的

看起来您的类没有这样的约束,因此编译器将IEnumerable<T>参数视为object(所有内容都可以转换为object)并调用(2),并传递单个项目object个带有参数的数组,即在这种情况下的实际调用是

await AddRangeAsync(new object[] { entities });

这应该使错误消息神秘化。

话虽如此,请使用where T : class约束或Cast扩展方法:

await AddRangeAsync(entities.Cast<object>());