Расширенные сценарии Entity Framework для веб-приложения MVC (10 из 10)

Том Дайкстра

Пример веб-приложения Университета Contoso демонстрирует создание ASP.NET приложений MVC 4 с помощью Entity Framework 5 Code First и Visual Studio 2012. Сведения о серии руководств см. в первом руководстве серии.

Примечание

Если вам не удается устранить проблему, скачайте завершенную главу и попытайтесь воспроизвести проблему. Как правило, решение проблемы можно найти, сравнивая код с готовым кодом. Некоторые распространенные ошибки и способы их устранения см. в разделе "Ошибки и обходные решения".

В предыдущем руководстве вы реализовали репозиторий и единицу рабочих шаблонов. В этом руководстве рассматриваются следующие темы:

  • Выполнение необработанных SQL-запросов.
  • Выполнение запросов без отслеживания.
  • Изучение запросов, отправленных в базу данных.
  • Working with proxy classes.
  • Отключение автоматического обнаружения изменений.
  • Отключение проверки при сохранении изменений.
  • Ошибки и обходные листы

Для большинства этих разделов вы будете работать с уже созданными страницами. Чтобы использовать необработанный SQL для выполнения массовых обновлений, вы создадите новую страницу, которая обновляет количество кредитов всех курсов в базе данных:

Снимок экрана: начальная страница

Чтобы использовать запрос без отслеживания, вы добавите новую логику проверки на страницу редактирования отдела:

Снимок экрана: страница редактирования отдела Университета Contoso с повторяющимся сообщением об ошибке администратора.

Выполнение необработанных SQL-запросов

API Entity Framework Code First включает методы, позволяющие передавать команды SQL непосредственно в базу данных. Вам доступны следующие варианты:

  • Использование метода DbSet.SqlQuery для запросов, которые возвращают типы сущностей. Возвращаемые объекты должны иметь тип, ожидаемый DbSet объектом, и они автоматически отслеживаются контекстом базы данных, если вы не отключите отслеживание. (См. следующий раздел о методе AsNoTracking .)
  • Database.SqlQuery Используйте метод для запросов, возвращающих типы, которые не являются сущностями. Возвращаемые данные не отслеживаются контекстом базы данных, даже если вы используете этот метод для извлечения типов сущностей.
  • Используйте Database.ExecuteSqlCommand для команд, отличных от запросов.

Одним из преимуществ использования платформы Entity Framework является возможность избежать слишком тесной привязки кода к конкретному способу хранения данных. Это достигается путем автоматического создания запросов и команд SQL, что позволяет упростить написание кода. Но существуют исключительные сценарии, когда необходимо выполнить определенные sql-запросы, созданные вручную, и эти методы позволяют обрабатывать такие исключения.

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

Вызов запроса, возвращающего сущности

Предположим, вы хотите GenericRepository , чтобы класс предоставлял дополнительную гибкость фильтрации и сортировки, не требуя создания производного класса с дополнительными методами. Один из способов добиться этого — добавить метод, который принимает SQL-запрос. Затем можно указать любой тип фильтрации или сортировки в контроллере, например Where предложение, зависящее от соединений или вложенного запроса. В этом разделе вы узнаете, как реализовать такой метод.

GetWithRawSql Создайте метод, добавив следующий код в GenericRepository.cs:

public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)
{
    return dbSet.SqlQuery(query, parameters).ToList();
}

В Файле CourseController.cs вызовите новый метод из Details метода, как показано в следующем примере:

public ActionResult Details(int id)
{
    var query = "SELECT * FROM Course WHERE CourseID = @p0";
    return View(unitOfWork.CourseRepository.GetWithRawSql(query, id).Single());
}

В этом случае можно было бы использовать GetByID этот метод, но вы используете GetWithRawSql этот метод, чтобы убедиться, что GetWithRawSQL этот метод работает.

Запустите страницу сведений, чтобы убедиться, что запрос на выборку работает (перейдите на вкладку "Курс ", а затем "Сведения " для одного курса).

Снимок экрана: страница сведений об университете Contoso.

Вызов запроса, возвращающего другие типы объектов

Ранее вы создали таблицу статистики учащихся на странице сведений, в которой было показано число учащихся на каждую дату регистрации. Код, который делает это в Файле HomeController.cs , использует LINQ:

var data = from student in db.Students
           group student by student.EnrollmentDate into dateGroup
           select new EnrollmentDateGroup()
           {
               EnrollmentDate = dateGroup.Key,
               StudentCount = dateGroup.Count()
           };

Предположим, вы хотите написать код, который извлекает эти данные непосредственно в SQL, а не с помощью LINQ. Для этого необходимо выполнить запрос, возвращающий что-то, отличное от объектов сущностей, то есть необходимо использовать Database.SqlQuery метод.

В Файле HomeController.cs замените инструкцию LINQ в About методе следующим кодом:

var query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount "
    + "FROM Person "
    + "WHERE EnrollmentDate IS NOT NULL "
    + "GROUP BY EnrollmentDate";
var data = db.Database.SqlQuery<EnrollmentDateGroup>(query);

Запустите страницу "О программе". На экран будут выведены те же данные, что и ранее.

Снимок экрана: страница

Вызов запроса на обновление

Предположим, что администраторы Университета Contoso хотят иметь возможность выполнять массовые изменения в базе данных, например изменять количество кредитов для каждого курса. Поскольку в университете ведется множество курсов, будет неэффективно извлекать их в виде сущностей и изменять по отдельности. В этом разделе вы реализуете веб-страницу, которая позволяет пользователю указать фактор, с помощью которого можно изменить количество кредитов для всех курсов, и вы внесете изменения, выполнив инструкцию SQL UPDATE . Веб-страница должна выглядеть так, как показано на следующем рисунке:

Снимок экрана: начальная страница

В предыдущем руководстве вы использовали универсальный репозиторий для чтения и обновления Course сущностей в контроллере Course . Для этой операции массового обновления необходимо создать новый метод репозитория, который отсутствует в универсальном репозитории. Для этого вы создадите выделенный CourseRepository класс, производный от GenericRepository класса.

В папке DAL создайте файл CourseRepository.cs и замените существующий код следующим кодом:

using System;
using ContosoUniversity.Models;

namespace ContosoUniversity.DAL
{
    public class CourseRepository : GenericRepository<Course>
    {
        public CourseRepository(SchoolContext context)
            : base(context)
        {
        }

        public int UpdateCourseCredits(int multiplier)
        {
            return context.Database.ExecuteSqlCommand("UPDATE Course SET Credits = Credits * {0}", multiplier);
        }

    }
}

В UnitOfWork.cs измените Course тип репозитория на GenericRepository<Course>CourseRepository:

private CourseRepository courseRepository;
public CourseRepository CourseRepository
{
    get
    {

        if (this.courseRepository == null)
        {
            this.courseRepository = new CourseRepository(context);
        }
        return courseRepository;
    }
}

В Файле CourseController.cs добавьте UpdateCourseCredits метод:

public ActionResult UpdateCourseCredits(int? multiplier)
{
    if (multiplier != null)
    {
        ViewBag.RowsAffected = unitOfWork.CourseRepository.UpdateCourseCredits(multiplier.Value);
    }
    return View();
}

Этот метод будет использоваться для обоих HttpGet и HttpPost. HttpGetUpdateCourseCredits При запуске метода переменная будет иметь значение NULL, multiplier а представление будет отображать пустое текстовое поле и кнопку отправки, как показано на предыдущем рисунке.

При нажатии кнопки "Обновить" и выполнении HttpPostmultiplier метода в текстовом поле будет введено значение. Затем код вызывает метод репозитория UpdateCourseCredits , который возвращает количество затронутых строк и это значение хранится в объекте ViewBag . Когда представление получает количество затронутых строк в ViewBag объекте, оно отображает это число вместо текстового поля и кнопку отправки, как показано на следующем рисунке:

Снимок экрана, на котором показана затронутая страница

Создайте представление в папке Views\Course для страницы "Кредиты на обновление курса":

Снимок экрана: диалоговое окно

В представлениях\Course\UpdateCourseCredits.cshtml замените код шаблона следующим кодом:

@model ContosoUniversity.Models.Course

@{
    ViewBag.Title = "UpdateCourseCredits";
}

<h2>Update Course Credits</h2>

@if (ViewBag.RowsAffected == null)
{
    using (Html.BeginForm())
    {
        <p>
            Enter a number to multiply every course's credits by: @Html.TextBox("multiplier")
        </p>
        <p>
            <input type="submit" value="Update" />
        </p>
    }
}
@if (ViewBag.RowsAffected != null)
{
    <p>
        Number of rows updated: @ViewBag.RowsAffected
    </p>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Выполните метод UpdateCourseCredits, выбрав вкладку Courses (Курсы), а затем добавив "/UpdateCourseCredits" в конец URL-адреса в адресной строке браузера (например, http://localhost:50205/Course/UpdateCourseCredits). Введите число в текстовое поле:

Снимок экрана: начальная страница

Нажмите кнопку Обновить. Отобразится число обработанных строк:

Снимок экрана: страница

Нажмите кнопку Back to List (Вернуться к списку), чтобы просмотреть список курсов с измененным числом зачетных баллов.

Снимок экрана: страница

Дополнительные сведения о необработанных sql-запросах см. в блоге команды разработчиков Entity Framework.

и без отслеживания

Когда контекст базы данных извлекает строки базы данных и создает объекты сущностей, которые представляют их, по умолчанию отслеживает, синхронизированы ли сущности в памяти с тем, что находится в базе данных. При обновлении сущности данные в памяти выступают в роли кэша. В веб-приложении такое кэширование часто не нужно, поскольку экземпляры контекста, как правило, существуют недолго (для каждого запроса создается и ликвидируется собственный экземпляр), и контекст, считывающий сущность, как правило, ликвидируется до того, как сущность будет использована снова.

Можно указать, отслеживает ли контекст объекты сущностей для запроса с помощью AsNoTracking метода. Как правило, это требуется в следующих сценариях:

  • Запрос получает такой большой объем данных, что отключение отслеживания может заметно повысить производительность.
  • Вы хотите присоединить сущность, чтобы обновить ее, но ранее вы получили ту же сущность для другой цели. Поскольку сущность уже отслеживается контекстом базы данных, присоединить сущность, которую требуется изменить, нельзя. Одним из способов предотвращения этого является использование AsNoTracking параметра с предыдущим запросом.

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

В Файле DepartmentController.cs добавьте новый метод, который можно вызвать из Edit и методов, чтобы убедиться, что ни один отдел не имеет одного администратора Create :

private void ValidateOneAdministratorAssignmentPerInstructor(Department department)
{
    if (department.PersonID != null)
    {
        var duplicateDepartment = db.Departments
            .Include("Administrator")
            .Where(d => d.PersonID == department.PersonID)
            .FirstOrDefault();
        if (duplicateDepartment != null && duplicateDepartment.DepartmentID != department.DepartmentID)
        {
            var errorMessage = String.Format(
                "Instructor {0} {1} is already administrator of the {2} department.",
                duplicateDepartment.Administrator.FirstMidName,
                duplicateDepartment.Administrator.LastName,
                duplicateDepartment.Name);
            ModelState.AddModelError(string.Empty, errorMessage);
        }
    }
}

Добавьте код в try блок HttpPostEdit метода, чтобы вызвать этот новый метод, если ошибок проверки нет. Теперь try блок выглядит следующим образом:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(
   [Bind(Include = "DepartmentID, Name, Budget, StartDate, RowVersion, PersonID")]
    Department department)
{
   try
   {
      if (ModelState.IsValid)
      {
         ValidateOneAdministratorAssignmentPerInstructor(department);
      }

      if (ModelState.IsValid)
      {
         db.Entry(department).State = EntityState.Modified;
         db.SaveChanges();
         return RedirectToAction("Index");
      }
   }
   catch (DbUpdateConcurrencyException ex)
   {
      var entry = ex.Entries.Single();
      var clientValues = (Department)entry.Entity;

Запустите страницу "Изменение отдела" и попробуйте изменить администратора отдела на преподавателя, который уже является администратором другого отдела. Вы получите ожидаемое сообщение об ошибке:

Снимок экрана: страница

Теперь снова запустите страницу "Изменение отдела", и на этот раз измените сумму бюджета . При нажатии кнопки "Сохранить" появится страница ошибки:

Снимок экрана: страница

Сообщение об ошибке исключения — "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key." Это произошло из-за следующей последовательности событий:

  • Этот Edit метод вызывает ValidateOneAdministratorAssignmentPerInstructor метод, который получает все отделы, у которых Ким Аберкромби в качестве администратора. Это приводит к чтению английского отдела. Так как это редактируемый отдел, сообщение об ошибке не сообщается. Однако в результате этой операции чтения сущность английского отдела, считываемая из базы данных, теперь отслеживается контекстом базы данных.
  • Метод Edit пытается установить Modified флаг для сущности английского отдела, созданной связывательом модели MVC, но это завершается ошибкой, так как контекст уже отслеживает сущность для английского отдела.

Одним из решений этой проблемы является сохранение контекста от отслеживания сущностей отдела в памяти, полученных запросом проверки. Нет недостатка в этом, так как вы не будете обновлять эту сущность или считывать ее снова таким образом, чтобы она была кэширована в памяти.

В файле DepartmentController.cs в методе ValidateOneAdministratorAssignmentPerInstructor не укажите отслеживание, как показано в следующем примере:

var duplicateDepartment = db.Departments
   .Include("Administrator")
   .Where(d => d.PersonID == department.PersonID)
   .AsNoTracking()
   .FirstOrDefault();

Повторите попытку изменить бюджет отдела. На этот раз операция прошла успешно, и сайт возвращается на страницу индекса отделов, где отображается измененная бюджетная стоимость.

Изучение запросов, отправленных в базу данных

В некоторых случаях полезно иметь возможность просмотреть фактические SQL-запросы, отправляемые в базу данных. Для этого можно проверить переменную запроса в отладчике или вызвать метод запроса ToString . Чтобы попробовать это, вы посмотрите на простой запрос, а затем посмотрите на то, что происходит с ним при добавлении параметров, таких как безотложная загрузка, фильтрация и сортировка.

В Controllers/CourseController замените Index метод следующим кодом:

public ViewResult Index()
{
    var courses = unitOfWork.CourseRepository.Get();
    return View(courses.ToList());
}

Теперь задайте точку останова в файле GenericRepository.csreturn query.ToList(); для инструкций return orderBy(query).ToList();Get метода. Запустите проект в режиме отладки и выберите страницу индекса курса. Когда код достигает точки останова, изучите query переменную. Отобразится запрос, отправляемый в SQL Server. Это простая Select инструкция:

{SELECT 
[Extent1].[CourseID] AS [CourseID], 
[Extent1].[Title] AS [Title], 
[Extent1].[Credits] AS [Credits], 
[Extent1].[DepartmentID] AS [DepartmentID]
FROM [Course] AS [Extent1]}

Снимок экрана: вкладка универсального репозитория веб-приложения. Выбрана переменная запроса.

Запросы могут быть слишком длинными для отображения в окнах отладки в Visual Studio. Чтобы просмотреть весь запрос, можно скопировать значение переменной и вставить его в текстовый редактор:

Снимок экрана: значение переменной с раскрывающимся меню, отображаемым при выборе. Выделен параметр

Теперь вы добавите раскрывающийся список на страницу индекса курса, чтобы пользователи могли фильтровать для определенного отдела. Вы отсортируете курсы по названию и укажите неотложную загрузку для свойства навигации Department . В Файле CourseController.cs замените Index метод следующим кодом:

public ActionResult Index(int? SelectedDepartment)
{
    var departments = unitOfWork.DepartmentRepository.Get(
        orderBy: q => q.OrderBy(d => d.Name));
    ViewBag.SelectedDepartment = new SelectList(departments, "DepartmentID", "Name", SelectedDepartment);

    int departmentID = SelectedDepartment.GetValueOrDefault(); 
    return View(unitOfWork.CourseRepository.Get(
        filter: d => !SelectedDepartment.HasValue || d.DepartmentID == departmentID,
        orderBy: q => q.OrderBy(d => d.CourseID),
        includeProperties: "Department"));
}

Метод получает выбранное значение раскрывающегося списка в параметре SelectedDepartment . Если ничего не выбрано, этот параметр будет иметь значение NULL.

Коллекция SelectList , содержащая все отделы, передается в представление раскрывающегося списка. Параметры, передаваемые конструктору SelectList , указывают имя поля значения, имя текстового поля и выбранный элемент.

Get Для метода Course репозитория код задает выражение фильтра, порядок сортировки и безотложную загрузку для свойства навигацииDepartment. Выражение фильтра всегда возвращается true , если в раскрывающемся списке ничего не выбрано (то есть SelectedDepartment имеет значение NULL).

В Views\Course\Index.cshtml непосредственно перед открывающим table тегом добавьте следующий код, чтобы создать раскрывающийся список и кнопку отправки:

@using (Html.BeginForm())
{
    <p>Select Department: @Html.DropDownList("SelectedDepartment","All")   
    <input type="submit" value="Filter" /></p>
}

Если точки останова по-прежнему GenericRepository заданы в классе, запустите страницу индекса курса. Продолжайте через первые два раза, когда код попадает в точку останова, чтобы страница отображалась в браузере. Выберите отдел из раскрывающегося списка и нажмите кнопку "Фильтр":

Снимок экрана: страница

На этот раз первая точка останова будет использоваться для запросов отделов к раскрывающемся списку. Пропустите это и просмотрите query переменную при следующем достижении кодом точки останова, чтобы увидеть, как Course выглядит запрос. Вы увидите примерно следующее:

{SELECT 
[Extent1].[CourseID] AS [CourseID], 
[Extent1].[Title] AS [Title], 
[Extent1].[Credits] AS [Credits], 
[Extent1].[DepartmentID] AS [DepartmentID], 
[Extent2].[DepartmentID] AS [DepartmentID1], 
[Extent2].[Name] AS [Name], 
[Extent2].[Budget] AS [Budget], 
[Extent2].[StartDate] AS [StartDate], 
[Extent2].[PersonID] AS [PersonID], 
[Extent2].[Timestamp] AS [Timestamp]
FROM  [Course] AS [Extent1]
INNER JOIN [Department] AS [Extent2] ON [Extent1].[DepartmentID] = [Extent2].[DepartmentID]
WHERE (@p__linq__0 IS NULL) OR ([Extent1].[DepartmentID] = @p__linq__1)}

Вы увидите, что запрос теперь является запросом JOIN , который загружает Department данные вместе с данными Course и содержит предложение WHERE .

Работа с классами прокси-сервера

Когда Entity Framework создает экземпляры сущностей (например, при выполнении запроса), они часто создаются как экземпляры динамически созданного производного типа, который выступает в качестве прокси-сервера для сущности. Этот прокси-сервер переопределяет некоторые виртуальные свойства сущности для вставки перехватчиков для автоматического выполнения действий при доступе к свойству. Например, этот механизм используется для поддержки отложенной загрузки связей.

В большинстве случаев вам не нужно знать об этом использовании прокси-серверов, но существуют исключения:

  • В некоторых сценариях может потребоваться запретить Entity Framework создавать экземпляры прокси-сервера. Например, сериализация экземпляров, не являющихся прокси-серверами, может быть более эффективной, чем сериализация экземпляров прокси-сервера.
  • При создании экземпляра класса сущности new с помощью оператора вы не получите экземпляр прокси-сервера. Это означает, что вы не получаете такие функции, как отложенная загрузка и автоматическое отслеживание изменений. Обычно это нормально; Обычно не требуется отложенная загрузка, так как вы создаете новую сущность, которая отсутствует в базе данных, и обычно вам не требуется отслеживание изменений, если вы явно помечаете сущность как Added. Однако если требуется отложенная загрузка и требуется отслеживание изменений, можно создать новые экземпляры сущностей с прокси-серверами с помощью Create метода DbSet класса.
  • Может потребоваться получить фактический тип сущности из типа прокси-сервера. Метод класса можно использовать GetObjectType для получения фактического ObjectContext типа сущности экземпляра прокси-типа.

Дополнительные сведения см. в разделе "Работа с прокси-серверами " в блоге команды Entity Framework.

Отключение автоматического обнаружения изменений

Платформа Entity Framework определяет, как была изменена сущность (и, соответственно, какие обновления требуется отправить в базу данных), сравнивая текущие значения сущности с исходными. Исходные значения сохраняются при запросе или присоединении сущности. Ниже перечислены некоторые из методов, которые приводят к автоматическому обнаружению изменений:

  • DbSet.Find
  • DbSet.Local
  • DbSet.Remove
  • DbSet.Add
  • DbSet.Attach
  • DbContext.SaveChanges
  • DbContext.GetValidationErrors
  • DbContext.Entry
  • DbChangeTracker.Entries

Если вы отслеживаете большое количество сущностей и вызываете один из этих методов много раз в цикле, вы можете получить значительные улучшения производительности, временно отключив автоматическое обнаружение изменений с помощью свойства AutoDetectChangesEnabled . Дополнительные сведения см. в статье об автоматическом обнаружении изменений.

Отключение проверки при сохранении изменений

При вызове SaveChanges метода Entity Framework по умолчанию проверяет данные во всех свойствах всех измененных сущностей перед обновлением базы данных. Если вы обновили большое количество сущностей и уже проверили данные, эта работа не требуется, и вы можете сделать процесс сохранения изменений занимает меньше времени, временно отключив проверку. Это можно сделать с помощью свойства ValidateOnSaveEnabled . Дополнительные сведения см. в разделе "Проверка".

Сводка

В этом руководстве описано, как использовать Entity Framework в приложении ASP.NET MVC. Ссылки на другие ресурсы Entity Framework можно найти на карте содержимого доступа к данным ASP.NET.

Дополнительные сведения о развертывании веб-приложения после его создания см. в ASP.NET схеме содержимого развертывания в библиотека MSDN.

Сведения о других разделах, связанных с MVC, такими как проверка подлинности и авторизация, см. в рекомендуемых ресурсах MVC.

Благодарности

  • Том Дайкстра написал исходную версию этого учебника и является старшим автором программирования в группе содержимого веб-платформа Майкрософт и инструментов.
  • Рик Андерсон (twitter @RickAndMSFT) совместно написал это руководство и сделал большую часть работы, обновив ее для EF 5 и MVC 4. Рик — старший писатель по программированию для Майкрософт, ориентированный на Azure и MVC.
  • Роуан Миллер и другие члены команды Entity Framework помогали с проверками кода и помогли отладить множество проблем с миграциями, которые возникли при обновлении учебника для EF 5.

VB

При первоначальном создании учебника мы предоставили как C#, так и версии VB завершенного проекта загрузки. В этом обновлении мы предоставляем C# скачиваемый проект для каждой главы, чтобы упростить начало работы в любом месте серии, но из-за ограничений времени и других приоритетов мы не сделали этого для VB. Если вы создаете проект VB с помощью этих учебников и хотите поделиться им с другими пользователями, сообщите нам об этом.

Ошибки и обходные пути

Не удается создать или теневое копирование

Сообщение об ошибке:

Не удается создать или теневое копирование DotNetOpenAuth.OpenId, если этот файл уже существует.

Решение:

Подождите несколько секунд и обновите страницу.

Update-Database не распознаны

Сообщение об ошибке:

Термин Update-Database не распознается как имя командлета, функции, файла скрипта или выполняемой программы. Проверьте орфографию имени или если путь включен, убедитесь, что путь правильный и повторите попытку. (Из Update-Database команды в PMC.)

Решение:

Закройте Visual Studio. Повторно откройте проект и повторите попытку.

Проверка завершена с ошибкой

Сообщение об ошибке:

Сбой проверки для одной или нескольких сущностей. Дополнительные сведения см. в свойстве EntityValidationErrors. (Из Update-Database команды в PMC.)

Решение:

Одной из причин этой проблемы является ошибка проверки при выполнении Seed метода. Советы по отладке Seed метода см. в разделе "Заполнения и отладка баз данных Entity Framework (EF)".

Ошибка HTTP 500.19

Сообщение об ошибке:

ошибка HTTP 500.19 — внутренняя ошибка сервера
Доступ к запрошенной странице невозможен, так как связанные данные конфигурации для страницы недопустимы.

Решение:

Одним из способов получения этой ошибки является наличие нескольких копий решения, каждый из которых использует один и тот же номер порта. Как правило, эту проблему можно решить, выйдя из всех экземпляров Visual Studio, а затем перезагрузив проект, над которым вы работаете. Если это не работает, попробуйте изменить номер порта. Щелкните правой кнопкой мыши файл проекта и выберите свойства. Выберите веб-вкладку и измените номер порта в текстовом поле "URL-адрес проекта ".

Ошибка при обнаружении экземпляра SQL Server

Сообщение об ошибке:

При подключении к SQL Server произошла ошибка, связанная с сетью или с определенным экземпляром. Сервер не найден или недоступен. Проверьте правильность имени экземпляра и настройку сервера SQL Server для удаленных подключений. (поставщик: сетевые интерфейсы SQL, ошибка: 26 — ошибка при обнаружении указанного сервера или экземпляра)

Решение:

Проверьте строку подключения. Если база данных была удалена вручную, измените имя базы данных в строке построения.