【问题标题】:Getting ObjectContext error even after calling ToList即使在调用 ToList 之后也会出现 ObjectContext 错误
【发布时间】:2015-02-20 22:47:01
【问题描述】:

当直接调用下面的方法时,当使用检索到的列表调用 Mapper.Map 时,我得到一个 ObjectDisposedException。

System.ObjectDisposedException:ObjectContext 实例已被释放,不能再用于需要连接的操作。

public IEnumerable<Models.Provider> Get(string owner)
{
    List<Data.Models.Provider> providers;

    using (var db = new Data.ProviderDirectoryContext())
    {
        providers = db.Providers.Where(p => p.Owner.Name == owner).ToList();
    }

    var dtoProviders = Mapper.Map<List<Data.Models.Provider>, List<Models.Provider>>(providers);
    return dtoProviders;
}

我以前有这样的代码(如下),我没有收到错误,但是在进行映射时数据库受到了冲击,而且花费的时间太长。在进行映射时,我不想访问数据库。

public IEnumerable<Models.Provider> Get(string owner)
{
    using (var db = new Data.ProviderDirectoryContext())
    {
        var providers = db.Providers.Where(p => p.Owner.Name == owner).ToList();
        var dtoProviders = Mapper.Map<List<Data.Models.Provider>, List<Models.Provider>>(providers);
        return dtoProviders;
    }
}

如何在进行映射之前检索所有数据?

这里是 DbContext 和 Data.Models.Provider 供您参考。

public class ProviderDirectoryContext : DbContext
{
    public DbSet<Owner> Owners { get; set; }

    public DbSet<Location> Locations { get; set; }
    public DbSet<LocationAuditLog> LocationAuditLog { get; set; }

    public DbSet<Office> Offices { get; set; }
    public DbSet<OfficePhoneNumber> OfficePhoneNumbers { get; set; }
    public DbSet<OfficeAuditLog> OfficeAuditLog { get; set; }
    public DbSet<OfficeDay> OfficeDays { get; set; }

    public DbSet<Provider> Providers { get; set; }
    public DbSet<ProviderPhoneNumber> ProviderPhoneNumbers { get; set; }
    public DbSet<ProviderAuditLog> ProviderAuditLog { get; set; }

    public DbSet<ProviderType> ProviderTypes { get; set; }
    public DbSet<ProviderSpecialty> ProviderSpecialties { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<Provider>().HasRequired(cn => cn.Owner).WithMany().WillCascadeOnDelete(false);
        modelBuilder.Entity<Office>().HasRequired(cn => cn.Owner).WithMany().WillCascadeOnDelete(false);
    }
}

public class Provider
{
    public int Id { get; set; }

    public int OwnerId { get; set; }
    public virtual Owner Owner { get; set; }

    public int? ProviderTypeId { get; set; }
    public virtual ProviderType ProviderType { get; set; }

    public int? ProviderSpecialtyId { get; set; }
    public virtual ProviderSpecialty ProviderSpecialty { get; set; }

    [Required]
    [StringLength(75)]
    public string FirstName { get; set; }
    [StringLength(75)]
    public string MiddleName { get; set; }
    [Required]
    [StringLength(75)]
    public string LastName { get; set; }

    [StringLength(100)]
    public string EmailAddress { get; set; }

    public virtual ICollection<ProviderPhoneNumber> PhoneNumbers { get; set; }

    public string Note { get; set; }

    public DateTime? InactiveOn { get; set; }

    public int OfficeId { get; set; }
    public virtual Office Office { get; set; }

    public virtual ICollection<ProviderAuditLog> AuditLog { get; set; }

    [Required]
    public DateTime CreatedOn { get; set; }
    [Required]
    [StringLength(75)]
    public string CreatedBy { get; set; }
    [Required]
    public DateTime ModifiedOn { get; set; }
    [Required]
    [StringLength(75)]
    public string ModifiedBy { get; set; }
}

感谢您的帮助!

【问题讨论】:

  • Data.Models.Provider 中的任何函数/属性可以访问任何上下文函数?
  • 感谢@StephenReindl 的回复。我认为我在Data.Models.Provider 中没有做任何特别的事情,但我已将其添加到帖子中。

标签: entity-framework ef-code-first


【解决方案1】:

问题在于Models.Provider 类包含其他类,例如Models.OfficeModels.PhoneNumbers,它们没有被查询急切加载。除此之外,Models.Provider 类需要被展平。 Mapper 想要递归地映射所有内容,并且它会继续下一个类。例如,Provider.Office.Location.Offices

解决方案是将Models.Provider 展平并将.Include() 添加到查询中,以便它急切地加载所需的数据。

我会再清理一下,但这目前正在工作。

public IEnumerable<Models.Provider> Get(string owner)
{
    List<Data.Models.Provider> providers;
    using (var db = new Data.ProviderDirectoryContext())
    {
        providers = db.Providers
            .Where(p => p.Owner.Name == owner)
            .Include("ProviderType")
            .Include("ProviderSpecialty")
            .Include("Office")
            .Include("PhoneNumbers")
            .ToList();
    }
    var dtoProviders = Mapper.Map<List<Data.Models.Provider>, List<Models.Provider>>(providers);
    return dtoProviders;
    }

public class Provider
{
    public int Id { get; set; }

    public int OwnerId { get; set; }

    public int OfficeId { get; set; }
    public string OfficeName { get; set; }

    public int? ProviderTypeId { get; set; }
    public string ProviderTypeName { get; set; }

    public int? ProviderSpecialtyId { get; set; }
    public string ProviderSpecialtyName { get; set; }

    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }

    public string EmailAddress { get; set; }

    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }

    public string Note { get; set; }

    public DateTime? InactiveOn { get; set; }

    public DateTime CreatedOn { get; set; }
    public string CreatedBy { get; set; }
    public DateTime ModifiedOn { get; set; }
    public string ModifiedBy { get; set; }
}

【讨论】:

    【解决方案2】:

    我不确定这对性能有多大帮助,但在 using 语句之外声明您不想处置的变量应该可以解决您的处置异常。

       public IEnumerable<Models.Provider> Get(string owner)
         {
    
        IEnumerable<Models.Provider> dtoProviders;
        using (var db = new Data.ProviderDirectoryContext())
        {
            List<Data.Models.Provider> providers = db.Providers.Where(p => p.Owner.Name == owner).ToList();
    
            dtoProviders = Mapper.Map<List<Data.Models.Provider>, List<Models.Provider>>(providers);
        }
    
    
        return dtoProviders;
    }
    

    【讨论】:

    • 谢谢@jackncoke。虽然这确实有助于解决例外情况,但性能很糟糕。大约有 6,000 个提供者,映射需要 36 多秒。
    • 您需要映射的每个属性吗?您可以仅使用您需要的内容创建该类的较短版本吗?这应该会减少您的映射时间。
    • 感谢@jackncode,但我发现了问题。我会发布答案。
    猜你喜欢
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 2018-12-23
    • 2013-04-14
    相关资源
    最近更新 更多