003 Entity Framework Core 2.x P3 插入數據和簡單查詢

003 Entity Framework Core 2.x P3 插入數據和簡單查詢


博客園文章Id:12709575


在Asp .Net Core項目中使用Entity Freamwork Core

項目架構

項目架構
項目架構

AspEFCore.Data

依賴項

Microsort.EntityFrameworkCore.Tools 遷移命令

Microsoft.EntityFrameworkCore.Design遷移引擎

Microsoft.Extensions.Logging.Debug 與Debug相關的日期記錄
Microsoft.Extensions.Logging.Console 將日誌輸出到控制檯的擴展

引用項目

AspEFCore.Domain.Models

AspEFCore.Domain.Models

依賴項

Microsoft.EntityFrameworkCore 與Debug相關的日期記錄
Microsoft.EntityFrameworkCore.SqlServer 將日誌輸出到控制檯的擴展

AspEFCore.Web

依賴項

Microsort.EntityFrameworkCore.Tools 遷移命令

創建以下實體類模型

using System.Collections.Generic;

namespace AspEFCore.DoMain.Models
{
    public class City
    {
        /// <summary>
        /// 主鍵Id
        /// </summary>
        public int CityId { get; set; }

        /// <summary>
        /// 外鍵Id
        /// </summary>
        public int ProvinceId { get; set; }

        /// <summary>
        /// 導航屬性
        /// </summary>
        public Province Province { get; set; }

        public IEnumerable<CityCompany> CityCompanies { get; set; }
        public Mayor Mayor { get; set; }
    }
}
namespace AspEFCore.DoMain.Models
{
    public class CityCompany
    {
       public int CityCompanyId { get; set; }

        public int CityId { get; set; }
        public City City { get; set; }

        public int CompanyId { get; set; }
        public Company Company { get; set; }
    }
}
using System;
using System.Collections.Generic;

namespace AspEFCore.DoMain.Models
{
    public class Company
    {
        public Company()
        {
            CityCompanies = new List<CityCompany>();
        }

        public int CompanyId { get; set; }

        public string Name { get; set; }

        public DateTime EstablishDate  { get; set; }

        public string LegalPerson { get; set; }

        public IEnumerable<CityCompany> CityCompanies { get; set; }
    }
}
namespace AspEFCore.DoMain.Models
{
    public class Mayor
    {
        public int MayOrId { get; set; }

        public int CityId { get; set; }
        public City City { get; set; }
    }
}
using System.Collections.Generic;

namespace AspEFCore.DoMain.Models
{
    public class Province
    {
        public Province()
        {
            Cities = new List<City>();
        }

        public int ProvinceId { get; set; }

        public string Name { get; set; }

        public int Population { get; set; }

        public IEnumerable<City> Cities { get; set; }
    }
}

注意:

  1. 在EFCore規則下,在實體類中凡是以實體類名稱+Id的形式或直接叫Id形式的簡單類型(int,或者是string)的屬性,EFCore默認它就是主鍵,並會自動自增.
  2. EFCore上下文實例是需要Disposable的,所以我們在使用上下文的時候如果是採用new的方式創建了上下文實例,那麼是需要使用using來進行包裹,如果使用的是容器注入的方式我們是不需要使用using的形式創建,也不需要手動的Disposable,容器機制會自動幫助我們進行釋放.

在Asp .Net Core中使用EFCore上下文的方式有兩種:

  1. 直接在using中new 出EFCore上下文實例.
  2. 使用asp.net 自帶的容器,進行構造函數注入的方式來使用,那麼我們就不在需要使用using來包裹,EFCore上下文實例了,因爲asp.net core容器會自動釋放該上下文實例資源.

在 EFCore 2.x中 在asp.net core 中如果使用了AddContext方式來注入EFCore 那麼會自動添加日誌記錄的功能,無需在另外引用依賴項,但是在EFCore3.x中,如果我們想要在控制檯中顯示一些,我們需要手動在DbContext繼承類中加入一些代碼,詳情查詢EFCore對日誌使用描述的 官方文檔,代碼如下:

我們需要在類體中加入以下靜態變量.

public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });

我們需要在重寫的OnConfiguring方法中配置日誌工廠

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
 {
     optionsBuilder.UseLoggerFactory(MyLoggerFactory);
 }

遷移

如果我們修改過模型類的結構或者添加或修改過一些種子數據,那麼我們需要先進行Add-Migration操作,值得注意的是Add-Migration後面起的名稱不能和之前已經存在的Add-Migration名稱重複.

Add-Migration命令執行成功之後,我們需要執行 Update-Database命令進行遷移,到此ModelDb之前就已經是同步狀態,知道下一次對Model進行添加,或修改時,我們需要再進行此類操作,進行模型和數據的同步操作,保證是同步狀態.

EFCore Insert 操作

  • _context.Provinces.Add(Province);
    • MyContext開始追蹤Province對象
  • _context.SaceChanges();
    • 檢查所有MyContext正在追蹤的對象
    • 讀取每一個對象的狀態
    • 生成SQL語句
    • 執行所有生成的SQL語句
    • 如果有返回數據的話,就獲取這些返回數據

Insert 操作

 var province = new Province
 {
     Name = "北京",
     Population = 2_000_000
 };
 
 this._context.Province.Add(province);
 this._context.Province.AddRange(province);

批量 Insert 操作

數據源

 var province = new Province
 {
     Name = "北京",
     Population = 2_000_000
 };

 var province2 = new Province
 {
     Name = "上海",
     Population = 1_000_000
 };

 var province3 = new Province
 {
     Name = "關東",
     Population = 3_000_000
 };

添加追蹤的方式1

this._context.Province.Add(province);
this._context.Province.Add(province2);
this._context.Province.Add(province3);

添加追蹤的方式2

this._context.Province.AddRange(province,province2,province3);

添加追蹤的方式3

this._context.Province.AddRange(new List<Province>
{
    province,province2,province
});

提交添加功能

 this._context.SaveChanges();

同時 Insert 兩個不同的對象

數據源:

var province = new Province
{
    Name = "天津",
    Population = 8_000_000
};

var company = new Company()
{
    Name = "TaiDa",
    EstablishDate = new DateTime(1990,1,1),
    LegalPerson = "Secret Man"
};

添加

this._context.AddRange(province, company);

提交

this._context.SaveChanges();

批量操作的大小限制

  • 默認大小顯示是由數據庫Provider定的.
    • 例如Sql Server 是1000個命令
  • 如果超出該大小,那麼超出的部分將作爲另外的批次來執行.

如果想修改此限制也是可以的,我們可以在AddDbContext方法中,修改限制,代碼如下:

 options.UseSqlServer(
                    _configuration.GetConnectionString("DefaultConnectionString"),
                    opts=>opts.MaxBatchSize(1000000));  //修改一次提交的命令的數量限制
            });

查詢


//查詢所有provinces表的數據
 var provinces = _context.Province.ToList();

 //帶過濾條件的查詢
 var provinces2 = _context.Province
     .Where(x => x.Name == "北京")
     .ToList();

 //使用Linq的方式查詢
 var provinces3 = (from p in _context.Province
     where p.Name == "上海"
     select p).ToList();

值得注意的是,在進行.ToList()方法之前,無論是查詢方法的方式(表達式樹),還是Linq表達式的方式,都只是構建了一個查詢表達式,並沒有實際去查詢數據庫,我們可以理解成是在拼接sql的過程,只有執行到類似如.ToList()或者.ToDictionary()或者.ToArray()等方法的時候纔會正在的發送生成好的sql腳本到數據庫中去進行查詢.

查詢注意事項:

案例代碼如下:

var provinces4 = _context.Province
    .Where(x => x.Name == "北京");

foreach (var province in provinces4)
{
    Console.WriteLine(province.Name);

    /*執行了一些耗時方法*/
}

上述代碼的問題在於,變量provinces4此時只是相當於一個表達式樹,在使用foreach對這個表達式樹進行遍歷時,此表達式樹會生成相應的sql去請求數據庫查詢數據,但是如果這個foreach循環執行的時間比較長的話,會導致數據庫連接長期處於被打開狀態(引發數據庫性能問題),此時如果有別的操作來,操作此表的話,就會出現一些意想不到的事情,所以在遍歷之前,我們最好使用ToList()方法之類的方式,先將此表達式應對的數據查詢到內存中(此處數據庫連接就會被關閉掉),再對查詢到數據進行處理.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章