Share via


MVC Web 應用程式的進階 Entity Framework 案例 (10)

By Tom Dykstra

Contoso University 範例 Web 應用程式示範如何使用 Entity Framework 5 Code First 和 Visual Studio 2012 建立 ASP.NET MVC 4 應用程式。 如需教學課程系列的資訊,請參閱本系列的第一個教學課程

注意

如果您遇到無法解決的問題, 請下載已完成的章節 ,並嘗試重現您的問題。 一般而言,您可以將程式碼與已完成的程式碼進行比較,以找出問題的解決方案。 如需一些常見的錯誤以及如何解決這些問題,請參閱 錯誤和因應措施。

在上一個教學課程中,您已實作存放庫和工作單元模式。 本教學課程涵蓋下列主題:

  • 執行原始 SQL 查詢。
  • 執行無追蹤查詢。
  • 檢查傳送至資料庫的查詢。
  • 使用 Proxy 類別。
  • 停用變更的自動偵測。
  • 儲存變更時停用驗證。
  • 錯誤和因應措施

對於大部分的主題,您將使用您已建立的頁面。 若要使用原始 SQL 進行大量更新,您將建立新的頁面,以更新資料庫中所有課程的點數:

顯示更新課程點數初始頁面的螢幕擷取畫面。數位 2 會在文字欄位中輸入。

若要使用無追蹤查詢,您會將新的驗證邏輯新增至 [部門編輯] 頁面:

顯示 Contoso University Department Edit 頁面的螢幕擷取畫面,其中包含重複的系統管理員錯誤訊息。

執行原始 SQL 查詢

Entity Framework Code First API 包含方法,可讓您直接將 SQL 命令傳遞至資料庫。 下列選項可供您選擇:

  • 針對傳回實體類型的查詢使用 DbSet.SqlQuery 方法。 傳回的物件必須是 物件預期的 DbSet 類型,除非您關閉追蹤,否則資料庫內容會自動追蹤這些物件。 (請參閱下列 AsNoTracking 關於 method.)
  • 針對傳回非實體類型的查詢使用 Database.SqlQuery 方法。 即使您使用這個方法來擷取實體類型,資料庫內容也不會追蹤傳回的資料。
  • 針對非查詢命令使用 Database.ExecuteSqlCommand

使用 Entity Framework 的優點之一,是它可避免將程式碼繫結至太接近儲存資料之特定方法的位置。 它可透過產生 SQL 查詢和命令來達成此目的,同時這也可讓您不必自行撰寫。 但當您需要執行手動建立的特定 SQL 查詢時,會有例外狀況,而且這些方法可讓您處理這類例外狀況。

如同在 Web 應用程式中執行 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 University 詳細資料頁面的螢幕擷取畫面。

呼叫傳回其他類型的物件的查詢

先前您已針對顯示每個註冊日期之學生數目的 About 頁面,建立學生統計資料方格。 在 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中,以下列程式碼取代 方法中的 About LINQ 語句:

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 University About 頁面的螢幕擷取畫面。

呼叫更新查詢

假設 Contoso University 系統管理員想要能夠在資料庫中執行大量變更,例如變更每個課程的點數。 如果該大學有大量的課程,擷取全部課程作為實體並個別進行變更的效率不佳。 在本節中,您將實作一個網頁,讓使用者能夠指定要變更所有課程點數的因素,而您將執行 SQL UPDATE 語句來進行變更。 網頁看起來將如下圖所示:

顯示更新課程點數初始頁面的螢幕擷取畫面。數位 2 會在文字欄位中輸入。

在上一個教學課程中,您已使用泛型存放庫來讀取和更新 Course 控制器中的 Course 實體。 針對此大量更新作業,您必須建立不在泛型存放庫中的新存放庫方法。 若要這樣做,您將建立衍生自 類別的 GenericRepository 專用 CourseRepository 類別。

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

這個方法將用於 HttpGetHttpPostHttpGetUpdateCourseCredits 當方法執行時, multiplier 變數會是 Null,而檢視會顯示空的文字方塊和送出按鈕,如上圖所示。

按一下 [ 更新 ] 按鈕並 HttpPost 執行 方法時, multiplier 將會在文字方塊中輸入值。 然後,程式碼會呼叫存放庫 UpdateCourseCredits 方法,這個方法會傳回受影響的資料列數目,而且該值會儲存在 物件中 ViewBag 。 當檢視收到 物件中 ViewBag 受影響的資料列數目時,它會顯示該數位,而不是文字方塊並提交按鈕,如下圖所示:

顯示 Contoso University Update Course 點數資料列受影響頁面的螢幕擷取畫面。

在 [更新課程點數] 頁面的 Views\Course 資料夾中建立檢視:

顯示 [新增檢視] 對話方塊的螢幕擷取畫面。更新課程點數會在 [檢視名稱] 文字欄位中輸入。

Views\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" 新增至瀏覽器位址列中的 URL 結尾 (例如:http://localhost:50205/Course/UpdateCourseCredits),以執行 UpdateCourseCredits 方法。 在文字方塊中輸入數目:

顯示 [更新課程點數初始] 頁面的螢幕擷取畫面,其中已輸入文字欄位中的數位 2。

按一下 [更新]。 您會看到受影響的資料列數目:

顯示 [更新課程點數] 頁面的螢幕擷取畫面,其中已更新資料列數目。

按一下 [回到清單],以查看課程與已修訂學分數的清單。

顯示 [課程索引] 頁面的螢幕擷取畫面。課程清單會顯示修訂的點數。

如需原始 SQL 查詢的詳細資訊,請參閱 Entity Framework 小組部落格上的 原始 SQL 查詢

不追蹤的查詢

當資料庫內容擷取資料庫資料列並建立代表它們的實體物件時,預設會追蹤記憶體中的實體是否與資料庫中的內容同步。 記憶體中的資料所扮演的角色是一個快取,並會在您更新實體時使用。 這個快取通常在 Web 應用程式當中是不需要的,因為內容執行個體通常壽命都很短 (每次要求都會建立一個新的並進行處置),並且通常讀取實體的內容都會在實體重新獲得利用前遭到處置。

您可以使用 方法來指定內容是否追蹤查詢的 AsNoTracking 實體物件。 您會想要進行這項操作的常見案例包括下列情況:

  • 查詢會擷取這類大量資料,而關閉追蹤可能會明顯增強效能。
  • 您想要附加實體以更新實體,但您先前已針對不同的用途擷取相同的實體。 由於實體已由資料庫內容進行追蹤,您無法連結到您想要變更的實體。 防止發生這種情況的其中一種方式是搭配先前的查詢使用 AsNoTracking 選項。

在本節中,您將實作商務邏輯,以說明這些案例的第二個。 具體而言,您將強制執行商務規則,指出講師不能是多個部門的系統管理員。

DepartmentController.cs中,新增您可以從 和 Create 方法呼叫 Edit 的新方法,以確保沒有任何兩個部門具有相同的系統管理員:

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

如果沒有任何驗證錯誤, HttpPostEdit 請在 方法的 區塊中 try 新增程式碼,以呼叫這個新方法。 區塊 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 會嘗試在 MVC 模型系結器所建立的英文部門實體上設定 Modified 旗標,但因為內容已經追蹤英文部門的實體而失敗。

此問題的其中一個解決方案是讓內容無法追蹤驗證查詢所擷取的記憶體內部部門實體。 這樣做沒有缺點,因為您不會更新此實體,或以受益于記憶體中快取的方式再次讀取實體。

DepartmentController.cs的 方法中 ValidateOneAdministratorAssignmentPerInstructor ,指定沒有追蹤,如下列所示:

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

重複您編輯部門 預算 金額的嘗試。 這次作業成功,網站會如預期般傳回 Departments Index 頁面,其中顯示修訂的預算值。

檢查傳送至資料庫的查詢

有時能夠看到傳送至資料庫的實際 SQL 查詢很有幫助。 若要這樣做,您可以檢查偵錯工具中的查詢變數,或呼叫查詢的 ToString 方法。 若要嘗試這麼做,您將查看簡單的查詢,然後在您新增積極式載入、篩選和排序等選項時,查看它會發生什麼情況。

Controllers/CourseController中,以下列程式碼取代 Index 方法:

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

現在,在 和 return orderBy(query).ToList(); 方法的 Get 語句上 return query.ToList(); ,于GenericRepository.cs中設定中斷點。 以偵錯模式執行專案,然後選取 [課程索引] 頁面。 當程式碼到達中斷點時,請檢查 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]}

顯示範例 Web 應用程式 [一般存放庫] 索引標籤的螢幕擷取畫面。已選取查詢變數。

查詢可能太長,無法在 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 null SelectedDepartment) 。

Views\Course\Index.cshtml中,緊接在開頭 table 標記之前,新增下列程式碼以建立下拉式清單和提交按鈕:

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

在類別中 GenericRepository 仍設定中斷點後,請執行 Course Index 頁面。 繼續執行程式碼叫用中斷點的前兩次,讓頁面顯示在瀏覽器中。 從下拉式清單中選取部門,然後按一下 [ 篩選]:

顯示 [課程索引] 頁面的螢幕擷取畫面,其中已選取 [經濟部門]。

這次第一個中斷點會用於下拉式清單的部門查詢。 請略過該變數,並在下次程式碼到達中斷點時檢視 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 子句。

使用 Proxy 類別

例如,當 Entity Framework 建立實體實例 (時,當您執行查詢) 時,通常會將它們建立為動態產生之衍生類型的實例,做為實體的 Proxy。 此 Proxy 會覆寫實體的某些虛擬屬性,以在存取屬性時自動插入執行動作的勾點。 例如,這個機制可用來支援延遲載入關聯性。

在大部分情況下,您不需要注意此 Proxy 的使用方式,但有例外狀況:

  • 在某些情況下,您可能會想要防止 Entity Framework 建立 Proxy 實例。 例如,序列化非 Proxy 實例可能會比序列化 Proxy 實例更有效率。
  • 當您使用 new 運算子具現化實體類別時,不會取得 Proxy 實例。 這表示您不會取得延遲載入和自動變更追蹤等功能。 這通常沒關係;您通常不需要延遲載入,因為您正在建立不在資料庫中的新實體,而且如果您明確將實體標示為 Added ,則通常不需要變更追蹤。 不過,如果您需要延遲載入,而且需要變更追蹤,您可以使用 類別的 DbSet 方法來建立 Create 具有 Proxy 的新實體實例。
  • 您可能會想要從 Proxy 類型取得實際的實體類型。 您可以使用 GetObjectType 類別的 ObjectContext 方法來取得 Proxy 類型實例的實際實體類型。

如需詳細資訊,請參閱 Entity Framework 小組部落格上的 使用 Proxy

停用自動偵測變更

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 屬性來執行此動作。 如需詳細資訊,請參閱驗證

總結

這會完成本系列教學課程,說明在 ASP.NET MVC 應用程式中使用 Entity Framework。 您可以在 ASP.NET 資料存取內容對應中找到其他 Entity Framework 資源的連結。

如需如何在建置 Web 應用程式之後部署 Web 應用程式的詳細資訊,請參閱 MSDN Library 中的 ASP.NET 部署內容對應

如需 MVC 相關其他主題的資訊,例如驗證和授權,請參閱 MVC 建議的資源

通知

  • Tom Dykstra 撰寫本教學課程的原始版本,是 Microsoft Web 平臺和工具內容小組的資深程式設計撰寫者。
  • Rick Anderson (twitter @RickAndMSFT) 共同撰寫本教學課程,並針對 EF 5 和 MVC 4 進行大部分的更新工作。 Rick 是 Microsoft 的資深程式設計撰寫者,著重于 Azure 和 MVC。
  • Rowan Miller 和 Entity Framework 小組的其他成員協助程式碼檢閱,並協助偵錯我們在更新 EF 5 教學課程時所發生的移轉許多問題。

VB

最初產生本教學課程時,我們同時提供已完成下載專案的 C# 和 VB 版本。 透過此更新,我們會為每個章節提供 C# 可下載的專案,讓您更輕鬆地在系列中的任何位置開始使用,但由於時間限制和其他優先順序,我們並未針對 VB 這麼做。 如果您使用這些教學課程建置 VB 專案,並願意與其他人共用,請讓我們知道。

錯誤和因應措施

無法建立/陰影複製

錯誤訊息:

當該檔案已經存在時,無法建立/陰影複製 'DotNetOpenAuth.OpenId'。

解決方案:

請稍候幾秒,然後重新整理頁面。

無法辨識Update-Database

錯誤訊息:

'Update-Database' 一詞無法辨識為 Cmdlet、函式、腳本檔案或可操作程式的名稱。 請檢查名稱拼字,如果名稱含有路徑,請確認路徑正確,然後再試一次。 (從 Update-Database PMC.) 中的 命令

解決方案:

結束 Visual Studio。 重新開啟專案,然後再試一次。

驗證失敗

錯誤訊息:

一或多個實體的驗證失敗。 如需詳細資訊,請參閱 'EntityValidationErrors' 屬性。 (從 Update-Database PMC.) 中的 命令

解決方案:

此問題的其中一個原因是方法執行時 Seed 發生驗證錯誤。 如需偵錯方法的 Seed 秘訣,請參閱植入和偵錯 Entity Framework (EF) DB

HTTP 500.19 錯誤

錯誤訊息:

HTTP 錯誤 500.19 - 內部伺服器錯誤
無法存取要求的頁面,因為頁面的相關設定資料無效。

解決方案:

您可以取得此錯誤的其中一種方式,就是有多個解決方案複本,每個複本都使用相同的埠號碼。 您通常可以結束 Visual Studio 的所有實例,然後重新開機您的工作專案,來解決此問題。 如果無法運作,請嘗試變更埠號碼。 以滑鼠右鍵按一下專案檔,然後按一下 [屬性]。 選取 [Web] 索引標籤,然後在 [ 專案 URL ] 文字方塊中變更埠號碼。

搜尋 SQL Server 執行個體時發生錯誤

錯誤訊息:

和 SQL Server 建立連線時,發生與網路相關或執行個體特定的錯誤。 找不到或無法存取伺服器。 檢查執行個體名稱是否正確以及 SQL Server 執行個體是否設定為允許遠端連接。 (提供者:SQL 網路介面,錯誤:26 - 搜尋指定的伺服器/執行個體時發生錯誤)

解決方案:

檢查連接字串。 如果您已手動刪除資料庫,請變更建構字串中的資料庫名稱。