繁体   English   中英

在ASP.NET MVC中将AutoMapper QueryableExtensions与Entity Framework一起使用会导致“操作可能破坏运行时的稳定性”异常

[英]Using AutoMapper QueryableExtensions with Entity Framework in ASP.NET MVC causes an “Operation could destabilize the runtime” exception

考虑以下代码:

protected override IEnumerable<IListModel> GetListInternal(
    IQueryModel2<Contact> queryModel) {
    /// Causes exception
    return this.Query(queryModel).Project().To<ContactListModel>().AsEnumerable();

    /// Does not cause exception
    return Mapper.Map<IQueryable<Contact>, IEnumerable<ContactListModel>>(this.Query(queryModel)).ToList();
}

当第一行返回时,我得到一个例外: 操作可能会使运行时不稳定 当第二行返回时,它工作正常。 据我了解,第二个返回实际上返回一个具体的IEnumerable<ContactListModel> ,但第一个返回没有返回。 我将.AsEnumerable()ToArray().ToList()附加到第一个返回值.ToList() ,我一直在获取异常。 因此,关于Project()返回的内容必须有所了解。 无论返回什么,都可能是IEnumerable<ContactListModel>从而传递了方法的返回要求,但是当它在管道中进行进一步处理时,它的具体对象正在引发异常。

具体来说,此方法返回的集合将传递到进行最终处理的ListWrapper<TEntity>类。 当我在集合上调用.Count()时,总是会抛出异常。

我急切地寻求有关解决投影问题的指导,因为第二次回报效率很低。 从MiniProfiler告诉有关使用此特定代码的页面的信息,我正在进行1204条重复的SQL查询,我想我们所有人都可以同意这是一个问题...谢谢您的任何建议!

这是Query()IQueryModel2<TEntity>样子:

public IQueryable<TEntity> Query(
    IQueryModel2<TEntity> queryModel = null) {
    return this.QueryInternal(queryModel);
}

private IQueryable<TEntity> QueryInternal(
    IQueryModel2<TEntity> queryModel) {
    IQueryable<TEntity> entities = this.Context.Set<TEntity>();

    if (queryModel != null) {
        if (queryModel.Entities != null) {
            entities = queryModel.Entities.AsQueryable();
        }

        if (queryModel.Predicate != null) {
            entities = entities.AsExpandable().Where(queryModel.Predicate);
        }
    }

    return entities;
}

public interface IQueryModel2<TEntity> {
    IEnumerable<TEntity> Entities { get; set; }

    Expression<Func<TEntity, bool>> Predicate { get; set; }

    SearchPostModel Search { get; set; }
}

更新(1)

public sealed class ContactListModel :
    ListModel {
    [Display(Order = 3)]
    public string Email { get; set; }
    [Display(Order = 1)]
    public string Name { get; set; }
    [Display(Order = 2)]
    public string Phone { get; set; }
    [Display(Order = 4)]
    public ContactType ContactType { get; set; }
}

internal sealed class ContactToContactListModel :
    Profile {
    protected override void Configure() {
        base.Configure();

        base.CreateMap<Contact, ContactListModel>()
            .ForMember(
                d => d.Name,
                o => o.MapFrom(
                    s => (s.FirstName + " " + s.LastName)))
            .IgnoreAllUnmapped();
    }
}

更新(2)

public static class AutoMapperExtensions {
    public static IMappingExpression<TSource, TDestination> IgnoreAllUnmapped<TSource, TDestination>(
        this IMappingExpression<TSource, TDestination> expression) {
        if (expression == null) {
            return null;
        }

        return IgnoreAllUnmappedInternal<TSource, TDestination>(expression, typeof(TSource), typeof(TDestination));
    }

    private static IMappingExpression<TSource, TDestination> IgnoreAllUnmappedInternal<TSource, TDestination>(
        IMappingExpression<TSource, TDestination> expression,
        Type sourceType,
        Type destinationType) {
        IEnumerable<string> unmappedProperties = Mapper.GetAllTypeMaps().First(
            m =>
                m.SourceType.Equals(sourceType)
                && m.DestinationType.Equals(destinationType)).GetUnmappedPropertyNames();

        foreach (string unmappedProperty in unmappedProperties) {
            expression.ForMember(unmappedProperty, o => o.Ignore());
        }

        return expression;
    }
}

更新3

因此,我将项目的程序集加载到LinqPad中,并在其中重新编码了查询代码。 多亏了.Dump()出色的.Dump()方法,我才能够观察到返回的对象实际上是什么。 因此,第一个返回默认返回DbQuery<T> ,第二个默认返回IList<T> 具有讽刺意味的是,当我在LinqPad中调用完全相同的代码序列时, 不会引发异常,并且得到了我期望的ListWrapper。 我真的不确定为什么它在ASP.NET MVC中不起作用。 尽管我什至不确定这是ASP.NET的错,因为它崩溃了属于不同程序集的库项目的代码...

由于LinqPad并未出现问题,因此我对如何解决此异常一无所知。 不知道这是否重要,但是我打算在解决方案中的所有项目中使用.NET 4.5.2,所以我不确定是否与此有关。

将Automapper升级到v3.2.0。

那解决了我遇到的确切问题。

对于从Automapper版本7.0.1开始在AzureDevOps的构建管道中使用VSTest平台运行的测试(mstest运行良好),返回了相同的例外。 支持这些测试的Automapper的最新版本是6.2.2。

从其他答案和他们的github问题来看,在我看来这是一个回归错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM