即使在调用ToList之后也会出现ObjectContext错误

时间:2015-02-20 22:47:02

标签: entity-framework ef-code-first

当直接调用下面的方法时,我在使用检索到的列表调用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; }
}

感谢您的帮助!

2 个答案:

答案 0 :(得分: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; }
}

答案 1 :(得分:0)

我不确定这对性能有多大帮助,但是声明你不想在using语句之外处理的变量应该修复你的dispose异常。

   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;
}