1. 程式人生 > >EF Core中,通過實體類向SQL Server數據庫表中插入數據後,實體對象是如何得到數據庫表中的默認值的

EF Core中,通過實體類向SQL Server數據庫表中插入數據後,實體對象是如何得到數據庫表中的默認值的

ask asd target 主鍵 行數 create count declare bold

我們使用EF Core的實體類向SQL Server數據庫表中插入數據後,如果數據庫表中有自增列或默認值列,那麽EF Core的實體對象也會返回插入到數據庫表中的默認值。

下面我們通過例子來展示,EF Core是怎麽獲取數據庫的默認值的。首先我們建立一個.NET Core控制臺項目,然後引入EF Core所需的NuGet包。

獲取自增列值


我們在SQL Server數據庫中建立一個表Person,該表有一個自增列ID為主鍵:

CREATE TABLE [dbo].[Person](
    [ID] [int] IDENTITY(1,1) NOT NULL
, [Name] [nvarchar](50) NULL, [Age] [int] NULL, CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]

然後我們使用EF Core的DB First將該表映射為實體類Person,如下所示:

public partial class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? Age { get; set; }
}

實體類Person生成的Fluent API代碼如下所示:

modelBuilder.Entity<Person>(entity =>
{
    entity.Property(e => e.Id).HasColumnName("ID");

    entity.Property(e 
=> e.Name).HasMaxLength(50); });

然後我們在Program類的Main方法中,通過實體類Person向數據庫Person表中插入一行數據:

class Program
{
    static void Main(string[] args)
    {
        using (var dbContext = new DemoDBContext())
        {
            Person person = new Person()
            {
                Name = "Tom",
                Age = 20
            };

            dbContext.Person.Add(person);
            dbContext.SaveChanges();

            Console.WriteLine(person.Id);//輸出:1
        }

        Console.WriteLine("Press any key to end...");
        Console.ReadKey();
    }
}

我們在dbContext.SaveChanges()這行代碼執行後,通過EF Core的後臺日誌可以查看到生成的SQL語句如下:

=============================== EF Core log started ===============================
Executed DbCommand (95ms) [Parameters=[@p0=‘?‘ (DbType = Int32), @p1=‘?‘ (Size = 50)], CommandType=‘Text‘, CommandTimeout=‘30‘]
SET NOCOUNT ON;
INSERT INTO [Person] ([Age], [Name])
VALUES (@p0, @p1);
SELECT [ID]
FROM [Person]
WHERE @@ROWCOUNT = 1 AND [ID] = scope_identity();
=============================== EF Core log finished ===============================

可以看到EF Core最後使用了scope_identity()函數,來返回了剛剛插入的自增列ID的值。

獲取默認值列


我們在SQL Server數據庫中再建立一個表Book,該表有一個默認值列BookCode為主鍵,其默認值為函數newid():

CREATE TABLE [dbo].[Book](
    [BookCode] [nvarchar](50) NOT NULL,
    [BookName] [nvarchar](50) NULL,
    [BookDescription] [nvarchar](50) NULL,
 CONSTRAINT [PK_Book] PRIMARY KEY CLUSTERED 
(
    [BookCode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Book] ADD  CONSTRAINT [DF_Book_BookCode]  DEFAULT (newid()) FOR [BookCode]
GO

然後我們使用EF Core的DB First將該表映射為實體類Book,如下所示:

public partial class Book
{
    public string BookCode { get; set; }
    public string BookName { get; set; }
    public string BookDescription { get; set; }
}

實體類Book生成的Fluent API代碼如下所示:

modelBuilder.Entity<Book>(entity =>
{
    entity.HasKey(e => e.BookCode);

    entity.Property(e => e.BookCode)
        .HasMaxLength(50)
        .HasDefaultValueSql("(newid())");

    entity.Property(e => e.BookDescription).HasMaxLength(50);

    entity.Property(e => e.BookName).HasMaxLength(50);
});

然後我們在Program類的Main方法中,通過實體類Book向數據庫Book表中插入一行數據:

class Program
{
    static void Main(string[] args)
    {
        using (var dbContext = new DemoDBContext())
        {
            Book book = new Book()
            {
                BookDescription = "English book",
                BookName = "English"
            };

            dbContext.Add(book);
            dbContext.SaveChanges();

            Console.WriteLine(book.BookCode);//輸出:B5AD3E33-3730-4545-8D45-9BD6DFCD5063
        }

        Console.WriteLine("Press any key to end...");
        Console.ReadKey();
    }
}

我們在dbContext.SaveChanges()這行代碼執行後,通過EF Core的後臺日誌可以查看到生成的SQL語句如下:

=============================== EF Core log started ===============================
Executed DbCommand (116ms) [Parameters=[@p0=‘?‘ (Size = 50), @p1=‘?‘ (Size = 50)], CommandType=‘Text‘, CommandTimeout=‘30‘]
SET NOCOUNT ON;
DECLARE @inserted0 TABLE ([BookCode] nvarchar(50), [_Position] [int]);
MERGE [Book] USING (
VALUES (@p0, @p1, 0)) AS i ([BookDescription], [BookName], _Position) ON 1=0
WHEN NOT MATCHED THEN
INSERT ([BookDescription], [BookName])
VALUES (i.[BookDescription], i.[BookName])
OUTPUT INSERTED.[BookCode], i._Position
INTO @inserted0;

SELECT [t].[BookCode] FROM [Book] t
INNER JOIN @inserted0 i ON ([t].[BookCode] = [i].[BookCode])
ORDER BY [i].[_Position];
=============================== EF Core log finished ===============================

我們發現EF Core實際上是用SQL Server的Merge語句往數據庫Book表中插入了數據,並且使用了Merge語句的OUTPUT關鍵字,來返回Book表中列BookCode插入的默認值。

EF Core中,通過實體類向SQL Server數據庫表中插入數據後,實體對象是如何得到數據庫表中的默認值的