使用EF Model First創建edmx模型,數據庫有數據的情況下,如何同時更新模型和數據庫


使用"EF Model First",我們可以很直觀地在edmx文件中創建數據模型,並根據模型生成數據庫,整個過程快速而高效。可當數據庫中有了一定的數據量,同時,可能需要對模型中字段、表、關系等進行更新,如何把模型中的變化映射到已經有一定數據量的數據庫呢?

 

本篇使用"EF Model First"創建1對多,多對多關系表,接着體驗如何把模型的更新映射到數據庫。edmx數據模型在如下幾個方面更新:
● 修改字段
● 添加字段
● 刪除字段
● 刪除表
● 刪除1對多關系
● 創建1對多關系
● 刪除多對多關系
● 創建多對多關系

 

  一、創建edmx數據模型並生成數據庫

→在MVC項目的Models文件夾下創建DataModel.edmx文件,點擊"添加"
→選擇"空模型",點擊"完成"
→創建如下實體

1

UserInfo、Role與R_UserInfoRole是1對多關系。
Role與ActionInfo是多對多關系。

→右鍵edmx文件界面,選擇"根據模型生成數據庫"
→選擇"新建連接"
→創建一個名稱為"ModelFirstTest"的數據庫,點擊"確定"
2
→提示"ModelFirstTest不存在,是否嘗試創建",選擇"是"
→在"生成數據庫向導"界面,勾選"是,在連接字符串中包含敏感數據",點擊"下一步"
3
→提示DDL另存為"Models\DataModel.edmx.sql",點擊"完成"
→點擊"執行"按鈕,執行DataModel.edmx.sql中的sql語句
4
→跳出數據庫登錄界面,輸入用戶名和密碼,點擊"連接"
→打開Sql Server Management Studio,發現已經創建了ModelFirstTest數據庫
5

並且數據庫自動為存在多對多關系的Role與ActionInfo生成了中間表ActionInfoRole。

 

  二、關於DataModel.edmx.sql

第一次生成的DataModel.edmx.sql不帶刪除外鍵、刪除表語句。回到DataModel.edmx界面,根據模型生成數據庫的流程再走一遍,這次,DataModel.edmx.sql比較完整。

 

□ 2.1 對於數據庫表中值為NULL的列處理

SET QUOTED_IDENTIFIER OFF;
GO
USE [ModelFirstTest];
GO
IF SCHEMA_ID(N'dbo') IS NULL EXECUTE(N'CREATE SCHEMA [dbo]');
GO

SET QUOTED_IDENTIFIER OFF意味着使用=或<>比較運算符,可以把表中列為null的行篩選出來:
● 使用WHERE column_name = NULL返回column_name列中包含空值的行。
● 使用WHERE column_name <> NULL返回column_name列中包含非空值的行。
● 使用 WHERE column_name <> XYZ_value 返回所有不為 XYZ_value 也不為NULL的行。

 

□ 2.2 刪除已經存在的外鍵

在R_UserInfoRole有2個外鍵。
在ActionInfo和Role的中間表ActionInfoRole有2個外鍵。

IF OBJECT_ID(N'[dbo].[FK_UserInfoR_UserInfoRole]', 'F') IS NOT NULL
    ALTER TABLE [dbo].[R_UserInfoRole] DROP CONSTRAINT [FK_UserInfoR_UserInfoRole];
GO
IF OBJECT_ID(N'[dbo].[FK_RoleR_UserInfoRole]', 'F') IS NOT NULL
    ALTER TABLE [dbo].[R_UserInfoRole] DROP CONSTRAINT [FK_RoleR_UserInfoRole];
GO
IF OBJECT_ID(N'[dbo].[FK_ActionInfoRole_ActionInfo]', 'F') IS NOT NULL
    ALTER TABLE [dbo].[ActionInfoRole] DROP CONSTRAINT [FK_ActionInfoRole_ActionInfo];
GO
IF OBJECT_ID(N'[dbo].[FK_ActionInfoRole_Role]', 'F') IS NOT NULL
    ALTER TABLE [dbo].[ActionInfoRole] DROP CONSTRAINT [FK_ActionInfoRole_Role];
GO
 
□ 2.3 刪除已經存在的表
 
UserInfo,Role,ActionInfo,R_UserInfoRole,ActionInfoRole總共5張表。
 
IF OBJECT_ID(N'[dbo].[UserInfo]', 'U') IS NOT NULL
    DROP TABLE [dbo].[UserInfo];
GO
IF OBJECT_ID(N'[dbo].[Role]', 'U') IS NOT NULL
    DROP TABLE [dbo].[Role];
GO
IF OBJECT_ID(N'[dbo].[ActionInfo]', 'U') IS NOT NULL
    DROP TABLE [dbo].[ActionInfo];
GO
IF OBJECT_ID(N'[dbo].[R_UserInfoRole]', 'U') IS NOT NULL
    DROP TABLE [dbo].[R_UserInfoRole];
GO
IF OBJECT_ID(N'[dbo].[ActionInfoRole]', 'U') IS NOT NULL
    DROP TABLE [dbo].[ActionInfoRole];
GO
 

□ 2.4 創建5張表

創建的時候不考慮主鍵和外鍵,主鍵和外鍵是后期加上。

-- Creating table 'UserInfo'
CREATE TABLE [dbo].[UserInfo] (
    [ID] int IDENTITY(1,1) NOT NULL,
    [LoginName] nvarchar(32)  NOT NULL,
    [LoginPwd] nvarchar(32)  NOT NULL,
    [SubTime] datetime  NOT NULL
);
GO
 
-- Creating table 'Role'
CREATE TABLE [dbo].[Role] (
    [ID] int IDENTITY(1,1) NOT NULL,
    [RoleName] nvarchar(32)  NOT NULL
);
GO
 
-- Creating table 'ActionInfo'
CREATE TABLE [dbo].[ActionInfo] (
    [ID] int IDENTITY(1,1) NOT NULL,
    [ActionInfoName] nvarchar(32)  NOT NULL
);
GO
 
-- Creating table 'R_UserInfoRole'
CREATE TABLE [dbo].[R_UserInfoRole] (
    [ID] int IDENTITY(1,1) NOT NULL,
    [IsEnable] bit  NOT NULL,
    [UserInfoID] int  NOT NULL,
    [RoleID] int  NOT NULL
);
GO
 
-- Creating table 'ActionInfoRole'
CREATE TABLE [dbo].[ActionInfoRole] (
    [ActionInfo_ID] int  NOT NULL,
    [Role_ID] int  NOT NULL
);
GO
 

□ 2.5 創建5張表的主鍵約束

-- Creating primary key on [ID] in table 'UserInfo'
ALTER TABLE [dbo].[UserInfo]
ADD CONSTRAINT [PK_UserInfo]
    PRIMARY KEY CLUSTERED ([ID] ASC);
GO
 
-- Creating primary key on [ID] in table 'Role'
ALTER TABLE [dbo].[Role]
ADD CONSTRAINT [PK_Role]
    PRIMARY KEY CLUSTERED ([ID] ASC);
GO
 
-- Creating primary key on [ID] in table 'ActionInfo'
ALTER TABLE [dbo].[ActionInfo]
ADD CONSTRAINT [PK_ActionInfo]
    PRIMARY KEY CLUSTERED ([ID] ASC);
GO
 
-- Creating primary key on [ID] in table 'R_UserInfoRole'
ALTER TABLE [dbo].[R_UserInfoRole]
ADD CONSTRAINT [PK_R_UserInfoRole]
    PRIMARY KEY CLUSTERED ([ID] ASC);
GO
 
-- Creating primary key on [ActionInfo_ID], [Role_ID] in table 'ActionInfoRole'
ALTER TABLE [dbo].[ActionInfoRole]
ADD CONSTRAINT [PK_ActionInfoRole]
    PRIMARY KEY NONCLUSTERED ([ActionInfo_ID], [Role_ID] ASC);
GO
 

 

□ 2.6 創建外鍵以及非聚集索引

關於聚集索引和非聚集索引:
● 聚集索引,好比一本漢語字典中,按頁搜索字,第1頁、第2頁......頁面是連續的,把頁數看作是聚集索引。
● 一個表中,聚集索引是唯一的,就好比一本漢語字典,只能按照一種順序,即頁數來排序。
● SQL Server默認為主鍵創建聚集索引。

● 非聚集索引,好比一本漢語字典中,按偏旁部首搜索字,偏旁部首本身是不連續的,把偏旁部首看作是非聚集索引。
● 經常被分組排序的列、外鍵列、頻繁給更新的列、頻繁修改索引的列......適合使用非聚集索引。

 

R_UserInfoRole表的UserInfoID和RoleID設置為外鍵和非聚集索引:

-- Creating foreign key on [UserInfoID] in table 'R_UserInfoRole'
ALTER TABLE [dbo].[R_UserInfoRole]
ADD CONSTRAINT [FK_UserInfoR_UserInfoRole]
    FOREIGN KEY ([UserInfoID])
    REFERENCES [dbo].[UserInfo]
        ([ID])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
 
-- Creating non-clustered index for FOREIGN KEY 'FK_UserInfoR_UserInfoRole'
CREATE INDEX [IX_FK_UserInfoR_UserInfoRole]
ON [dbo].[R_UserInfoRole]
    ([UserInfoID]);
GO
 
-- Creating foreign key on [RoleID] in table 'R_UserInfoRole'
ALTER TABLE [dbo].[R_UserInfoRole]
ADD CONSTRAINT [FK_RoleR_UserInfoRole]
    FOREIGN KEY ([RoleID])
    REFERENCES [dbo].[Role]
        ([ID])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
 
-- Creating non-clustered index for FOREIGN KEY 'FK_RoleR_UserInfoRole'
CREATE INDEX [IX_FK_RoleR_UserInfoRole]
ON [dbo].[R_UserInfoRole]
    ([RoleID]);
GO
 

 

ActionInfoRole設置外鍵和非聚集索引:

-- Creating foreign key on [ActionInfo_ID] in table 'ActionInfoRole'
ALTER TABLE [dbo].[ActionInfoRole]
ADD CONSTRAINT [FK_ActionInfoRole_ActionInfo]
    FOREIGN KEY ([ActionInfo_ID])
    REFERENCES [dbo].[ActionInfo]
        ([ID])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
GO
 
-- Creating foreign key on [Role_ID] in table 'ActionInfoRole'
ALTER TABLE [dbo].[ActionInfoRole]
ADD CONSTRAINT [FK_ActionInfoRole_Role]
    FOREIGN KEY ([Role_ID])
    REFERENCES [dbo].[Role]
        ([ID])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
 
-- Creating non-clustered index for FOREIGN KEY 'FK_ActionInfoRole_Role'
CREATE INDEX [IX_FK_ActionInfoRole_Role]
ON [dbo].[ActionInfoRole]
    ([Role_ID]);
GO
 

  三、更新模型再映射到數據庫

在更新模型之前,為每張表添加數據。

□ 3.1 模型修改字段

把UserInfo的LoginName改成LoginName1,並把字符串長度從nvarchar(32)變成nvarchar(64)

→在DataModel.edmx中修改
6
→右鍵界面,選擇"根據模型生成數據庫"
→點擊"完成",生成更新過的"DataModel.edmx.sql"
但是,數據庫有了數據,不能丟掉現有的表,不能在這里直接運行,必須到數據庫中更新。
→右鍵DataModel.edmx中UserInfo表,選擇"表映射"
7
可見,在DataModel.edmx層面已經完成了映射。
→在數據庫執行修改列名、改變列名長度語句

EXEC sp_rename '[dbo].[UserInfo].[LoginName]','LoginName1'
ALTER TABLE [dbo].[UserInfo] ALTER COLUMN [LoginName1] nvarchar(64)

 

□ 3.2 模型添加字段

在UserInfo中增加類型為small int的DelFlag字段。

→在DataModel.edmx中添加
8
→右鍵界面,選擇"根據模型生成數據庫"
→點擊"完成",生成更新過的"DataModel.edmx.sql"
但是,數據庫有了數據,不能丟掉現有的表,不能在這里直接運行,必須到數據庫中更新。
→右鍵DataModel.edmx中UserInfo表,選擇"表映射"
9
可見,在DataModel.edmx層面已經完成了映射。
→在數據庫執行添加列語句

ALTER TABLE [dbo].[UserInfo] ADD [DelFlag] smallint not null default 0

 

□ 3.3 刪除字段

把UserInfo中的DelFlag字段刪除。

→在DataModel.edmx中刪除
→右鍵界面,選擇"根據模型生成數據庫"
→點擊"完成",生成更新過的"DataModel.edmx.sql"
但是,數據庫有了數據,不能丟掉現有的表,不能在這里直接運行,必須到數據庫中更新。
→右鍵DataModel.edmx中UserInfo表,選擇"表映射"
10
可見,在DataModel.edmx層面已經完成了映射。
→在數據庫執行刪除列語句
先要刪除列相關的約束,再刪除

ALTER TABLE [dbo].[UserInfo] DROP CONSTRAINT DF__UserInfo__DelFla__0AD2A005
ALTER TABLE [dbo].[UserInfo] DROP COLUMN [DelFlag]

 

□ 3.4 刪除1對多關系

刪除R_UserInfoRole與UserInfo和Role的2組1對多關系。

→在DataModel.edmx中刪除2組關聯
→在DataModel.edmx中把R_UserInfoRole中的UserInfoID和RoleID屬性刪除
→右鍵界面,選擇"根據模型生成數據庫"
→在數據庫中

先刪除R_UserInfoRole的外鍵約束:

IF OBJECT_ID(N'[dbo].[FK_UserInfoR_UserInfoRole]', 'F') IS NOT NULL
    ALTER TABLE [dbo].[R_UserInfoRole] DROP CONSTRAINT [FK_UserInfoR_UserInfoRole];
GO
IF OBJECT_ID(N'[dbo].[FK_RoleR_UserInfoRole]', 'F') IS NOT NULL
    ALTER TABLE [dbo].[R_UserInfoRole] DROP CONSTRAINT [FK_RoleR_UserInfoRole];
GO

 

然后刪除R_UserInfoRole的外鍵UserInfoID和RoleID,先刪除列的索引再刪除外鍵:

DROP INDEX [dbo].[R_UserInfoRole].[IX_FK_UserInfoR_UserInfoRole]    
ALTER TABLE [dbo].[R_UserInfoRole] DROP COLUMN [UserInfoID]
 
DROP INDEX [dbo].[R_UserInfoRole].[IX_FK_RoleR_UserInfoRole]    
ALTER TABLE [dbo].[R_UserInfoRole] DROP COLUMN [RoleID]


□ 3.5 刪除表

刪除R_UserInfoRole。當然,在刪除表之前首先要刪除表的各種關聯,

→在DataModel.edmx中刪除R_UserInfoRole
→右鍵界面,選擇"根據模型生成數據庫"
→在數據庫中刪除表

DROP TABLE [dbo].[R_UserInfoRole]

 

□ 3.6 創建1對多關系

在DataModel.edmx中,創建R_UserInfoRole1,然后分別和UserInfo,Role建立1對多關系。

→在DataModel.edmx中,創建R_UserInfoRole1
11
→右鍵界面,選擇"根據模型生成數據庫"
→數據庫生成R_UserInfoRole1

先生成表R_UserInfoRole1:

CREATE TABLE [dbo].[R_UserInfoRole1] (
    [ID] int IDENTITY(1,1) NOT NULL,
    [IsEnable] bit  NOT NULL
);
GO

 

為R_UserInfoRole1增加主鍵:

ALTER TABLE [dbo].[R_UserInfoRole1]
ADD CONSTRAINT [PK_R_UserInfoRole1]
    PRIMARY KEY CLUSTERED ([ID] ASC);
GO

→在DataModel.edmx中,創建R_UserInfoRole1與UserInfo,Role的2組關聯
12
→右鍵界面,選擇"根據模型生成數據庫"
→在數據庫中

先為R_UserInfoRole1增加UserInfoID和RoleID列:

ALTER TABLE [dbo].[R_UserInfoRole1] ADD [UserInfoID] int not null
ALTER TABLE [dbo].[R_UserInfoRole1] ADD [RoleID] int not null

 

再為R_UserInfoRole1的UserInfoID和RoleID列添加外界約束和對應的非聚集索引:

-- Creating foreign key on [UserInfoID] in table 'R_UserInfoRole1'
ALTER TABLE [dbo].[R_UserInfoRole1]
ADD CONSTRAINT [FK_UserInfoR_UserInfoRole1]
    FOREIGN KEY ([UserInfoID])
    REFERENCES [dbo].[UserInfo]
        ([ID])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
 
-- Creating non-clustered index for FOREIGN KEY 'FK_UserInfoR_UserInfoRole1'
CREATE INDEX [IX_FK_UserInfoR_UserInfoRole1]
ON [dbo].[R_UserInfoRole1]([UserInfoID]);
GO
 
-- Creating foreign key on [RoleID] in table 'R_UserInfoRole1'
ALTER TABLE [dbo].[R_UserInfoRole1]
ADD CONSTRAINT [FK_RoleR_UserInfoRole1]
    FOREIGN KEY ([RoleID])
    REFERENCES [dbo].[Role]
        ([ID])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
 
-- Creating non-clustered index for FOREIGN KEY 'FK_RoleR_UserInfoRole1'
CREATE INDEX [IX_FK_RoleR_UserInfoRole1]
ON [dbo].[R_UserInfoRole1]([RoleID]);
GO
 

 

□ 3.7 刪除多對多關系

刪除ActionInfo與Role的多對多關系。

→在DataModel.edmx中,刪除ActionInfo與Role的關聯
→右鍵界面,選擇"根據模型生成數據庫"
→在數據庫中刪除ActionInfoRole中間表

DROP TABLE [dbo].[ActionInfoRole]

 

□ 3.8 創建多對多關系

→在DataModel.edmx中,重新創建ActionInfo與Role的關聯
→右鍵界面,選擇"根據模型生成數據庫"
→在數據庫中

先創建ActionInfo與Role的中間表ActionInfoRole:

CREATE TABLE [dbo].[ActionInfoRole] (
    [ActionInfo_ID] int  NOT NULL,
    [Role_ID] int  NOT NULL
);
GO

 

為中間表ActionInfoRole創建外鍵約束和非聚集索引:

-- Creating foreign key on [ActionInfo_ID] in table 'ActionInfoRole'
ALTER TABLE [dbo].[ActionInfoRole]
ADD CONSTRAINT [FK_ActionInfoRole_ActionInfo]
    FOREIGN KEY ([ActionInfo_ID])
    REFERENCES [dbo].[ActionInfo]
        ([ID])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
GO
 
-- Creating foreign key on [Role_ID] in table 'ActionInfoRole'
ALTER TABLE [dbo].[ActionInfoRole]
ADD CONSTRAINT [FK_ActionInfoRole_Role]
    FOREIGN KEY ([Role_ID])
    REFERENCES [dbo].[Role]
        ([ID])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
 
-- Creating non-clustered index for FOREIGN KEY 'FK_ActionInfoRole_Role'
CREATE INDEX [IX_FK_ActionInfoRole_Role]
ON [dbo].[ActionInfoRole]
    ([Role_ID]);
GO


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM