Как решить "есть ли уже открытый хранилище данных, связанное с этим соединением" - PullRequest
0 голосов
/ 31 декабря 2018

Основная проблема заключается в том, что когда веб-приложение запускается в Интернете, когда нагрузка высока, возникает исключение, говорящее о том, что уже открыт считыватель данных.

Ниже приведены спецификации, которые мы используем:

  • Entityframework 5.0.0
  • База данных MySQL

Есть ли способ решения этой проблемы без блока using(){}?Основная проблема этого подхода заключается в том, что при закрытии блока using я не могу расширить отношения внешнего ключа объектов entityframework внутри представления html.

Я также прилагаю некоторый исходный код, показывающий, как мы сохраняем один контекст базы данных черезвся заявка

public abstract class AbstractService
{
    public Entities db_model
    {
        get
        {
            return DbContext.Instance.db_model;
        }
    }
}

public class DbContext
{
    public Entities db_model = new Entities();
    private static DbContext _dbContext;

    public static DbContext Instance
    {
        get
        {
            if(_dbContext == null)
            {
                _dbContext = new DbContext();
            }
            return _dbContext;
        }
    }
}

1 Ответ

0 голосов
/ 31 декабря 2018

Этот ответ конкретно относится к проблеме, упомянутой в вопросе об использовании загруженных объектов в представлении ASP.NET.Вопрос касается способа решения этой проблемы без блока using или утилизации DbContext, однако я предлагаю сделать именно это.

Причина в том, что обычно желательно не использовать объекты Entity Framework в представлениях ASP.NET, потому что эти объекты намного больше, чем просто объекты POCO;они скрывают логику, которая позволяет им выступать в качестве прокси-сервера для базовой базы данных, поэтому у них есть скрытая зависимость от состояния DbContext, которое их создало.

Вот надуманный пример использования моделей EF для Employee и Department с DbContext:

public class CompanyDbContext : DbContext
{
    public DbSet<Department> Departments { get; set; }
    public DbSet<Employee> Employees { get; set; }
}

public class Department
{
    public long Id { get; set; }
    public virtual ICollection<Employee> Employees { get; set; }
}

public class Employee
{
    public long Id { get; set; }
    public long DepartmentId { get; set; }
    public virtual Department Department { get; set; }
}

Если бы они использовались в приложении ASP.NET, я бы создалнекоторые отдельные модели, которые не привязаны к Entity Framework, для использования в ASP.NET.Например:

public class DepartmentModel
{
    public long Id { get; set; }
    public List<EmployeeModel> Employees { get; set; }
}

public class EmployeeModel
{
    public long Id { get; set; }
    public long DepartmentId { get; set; }
}

Несколько соображений:

  1. Согласно документам MSDN, "A DbContext представляет собой комбинацию UnitOfWork и репозиторияпаттерны " - https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.dbcontext?redirectedfrom=MSDN&view=entity-framework-6.2.0 - Поэтому DbContext должно быть как можно более коротким.

  2. При загрузке данных из контекста связанные объекты могут быть извлечены с использованием DbSet<>.Include() - https://docs.microsoft.com/en-us/ef/ef6/querying/related-data

  3. Вообще говоря, имеет смысл определитьсоедините слой «data» со слоем «view» - по разным причинам, некоторые из которых перечислены здесь: https://docs.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5 - это включает отображение между объектами EF и моделями POCO.

Логика, которая используется для запроса DbContext, будет запрашивать данные с использованием EF и возвращать эти данные с использованием моделей POCO, так что только логика, имеющая непосредственное отношение к DbContext, имеетучастие в объектах EF.Например:

    public List<DepartmentModel> GetAllDepartments()
    {
        using (var ctx = new CompanyDbContext())
        {
            // Ensure that related data is loaded
            var departments = ctx.Departments
                .Include(d => d.Employees);

            // Manual mapping by converting into a new set of models to be used by the Views
            var models = departments
                .Select(d => new DepartmentModel
                {
                    Id = d.Id,
                    Employees = d.Employees
                             .Select(e => new EmployeeModel
                             {
                                 Id = e.Id,
                                 DepartmentId = e.DepartmentId
                             })
                             .ToList(),
                })
                .ToList();

            return models;
        }
    }

Возможность использовать эти модели POCO, требуя некоторого дополнительного стандартного кода, обеспечивает полное разделение между DbContext и ASP.NET, позволяя использовать данные без ASP.NET.Представления / контроллеры, связанные с временем жизни или состоянием DbContext.

Иногда это может выглядеть так, как если бы этот подход нарушал принцип «СУХОГО», однако я хотел бы отметить, что объекты EF и объекты ViewModel существуют для решения разных проблем, и весьма часто объекты ViewModel принимают разныеформировать или даже требовать дополнительных полей / атрибутов, которые не подходят для добавления в классы EF.

Наконец, вышеупомянутое использует «ручное» отображение, но если отображения действительно просты и понятны, тоВместо этого может иметь смысл использовать AutoMapper: Самый чистый способ привязать объект к DTO с помощью Linq Select?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...