十、Entity Framework Core 3.1入門教程-執行原生SQL

本文章是根據 微軟MVP solenovex(楊旭)老師的視頻教程編寫而來,再加上本身的一些理解。
視頻教程地址:https://www.bilibili.com/video/BV1xa4y1v7rR
GitHub源碼:https://github.com/hllive/LearnEFCore3.1git

無主鍵的Entity

  • .NetCore3.1容許無主鍵的Entity或Model
  • 它們不會被追蹤,至關因而只讀的
  • 映射到沒有主鍵的Table或View

如何在EFCore中使用原生SQL語句或執行存儲過程以及視圖
首先執行兩個SQL腳本,一個視圖和一個存儲過程github

CREATE VIEW ViewPlayerClub
AS
    SELECT p.Id[PlayerId],p.Name[PlayerName],c.Name[ClubName],c.City[ClubCity]
    FROM Players p INNER JOIN Clubs c ON p.ClubId=c.Id
GO
CREATE PROCEDURE RemoveGamePlayer
    @PlayerId UNIQUEIDENTIFIER
AS
BEGIN
    SET NOCOUNT ON;
    DELETE FROM GamePlayer WHERE PlayerId=@PlayerId
END
GO

根據視圖ViewPlayerClub建立一個類sql

public class PlayerClub
{
    public Guid PlayerId { get; set; }
    public string PlayerName { get; set; }
    public string ClubName { get; set; }
    public string ClubCity { get; set; }
}

再把這個類添加到DBContext中ide

public DbSet<PlayerClub> PlayerClubs { get; set; }

DbSet使用這個沒有主鍵的類是不行的,怎麼才能使用無主鍵的類呢?
能夠在OnModelCreating()方法裏設置一下ui

modelBuilder.Entity<PlayerClub>()
    .HasNoKey()//設置沒有主鍵
    .ToView("ViewPlayerClub");//若是不寫這句,當遷移的時候還會建立一個PlayerClub的Table,應該把這個類映射到一個視圖上

針對這種沒有主鍵的model查詢出來都是沒法追蹤的code

例子視頻

[HttpGet("PlayerClub")]
public IActionResult GetViewPlayerClub()
{
    var playerClub = _dbContext.PlayerClubs.Where(px => px.ClubCity.Contains("貴州")).ToList();
    return Ok(playerClub);
}

生成的SQL語句教程

SELECT [v].[ClubCity], [v].[ClubName], [v].[PlayerId], [v].[PlayerName]
FROM [ViewPlayerClub] AS [v]
WHERE CHARINDEX(N'貴州', [v].[ClubCity]) > 0

若是使用_dbContext.PlayerClubs.Find(Guid id)在編譯的時候不會出錯,但運行確定會報錯,由於Find()裏的參數是主鍵get

原生SQL查詢

執行原生SQL查詢有兩種方法源碼

  • .FromSqlRaw("SELECT *...") 直接寫SQL語句
  • .FromSqlRawAsync("SELECT *...")
  • .FromSqlInterpolated("$SELECT *...WHERE x={var}") SQL語句須要使用參數
  • .FromSqlInterpolatedAsync("$SELECT *...WHERE x={var}")

FromSqlRawFromSqlInterpolated是DbSet()的方法,因此只能針對DbSet方法執行,須要在DbSet()後使用FromSqlRaw

使用FromSqlRaw()方法

[HttpGet("SqlTest")]
public IActionResult GetSqlTest1()
{
    var leagues = _dbContext.Leagues.FromSqlRaw("SELECT * FROM Leagues").ToList();
    return Ok(leagues);
}

生成的SQL語句就是FromSqlRaw()方法裏的語句

使用FromSqlInterpolated()方法

[HttpGet("SqlTest1")]
public IActionResult GetSqlTest1([FromQuery] string name)
{
    //使用帶參數的FromSqlInterpolated
    var leagues = _dbContext.Leagues
        .FromSqlInterpolated($"SELECT * FROM Leagues WHERE Name LIKE N'%{name}%'")
        .ToList();
    return Ok(leagues);
}

生成的SQL語句就是FromSqlInterpolated()方法的語句,可是會使用SQL參數做爲查詢值

exec sp_executesql N'SELECT * FROM Leagues WHERE Name LIKE N''%@p0%''
',N'@p0 nvarchar(4000)',@p0=N'足球'

原生SQL查詢的要求

  • 必須返回Entity類型的全部屬性,通常都是SELECT *
  • 字段名和Entity的屬性名必須匹配
  • 沒法包含關聯的數據,不能寫JOIN語句
  • 只能查詢已知的Entity,也就是Context中設定好的或間接能追蹤到的數據

執行非查詢類SQL

  • Context.Database.ExecuteSqlRaw()
  • Context.Database.ExecuteSqlRawAsync()
  • Context.Database.ExecuteSqlInterpolated()
  • Context.Database.ExecuteSqlInterpolatedAsync()
  • 沒法用於查詢
  • 只能返回影響的行數
[HttpGet("SqlTest2")]
public IActionResult GetSqlTest2()
{
    //使用ExecuteSqlRaw
    var count = _dbContext.Database.ExecuteSqlRaw("EXEC [dbo].[RemoveGamePlayer] {0}", new Guid(""));
    //使用ExecuteSqlInterpolated
    var counts = _dbContext.Database.ExecuteSqlInterpolated($"EXEC [dbo].[RemoveGamePlayer] {new Guid("")}");
    return Ok(new { count, counts });
}

生成的SQL語句兩個都同樣

博客文章能夠轉載,但不能夠聲明爲原創

相關文章
相關標籤/搜索