網站首頁 編程語言 正文
一、理解Code First及其約定和配置
傳統設計應用的方式都是由下而上的,即我們習慣優先考慮數據庫,然后使用這個以數據為中心的方法在數據之上構建應用程序。這種方法非常適合于數據密集的應用或者數據庫很可能包含多個應用使用的業務邏輯的應用。對于這種應用,如果要使用EF的話,我們必須使用Database First方式。
設計應用的另一種方法就是以領域為中心的方式(領域驅動設計DDD)。DDD是一種由上而下的方式,我們通過從實現應用所需要的領域模型和實體的角度思考,從而開始設計應用。數據庫很少用來用于領域模型數據的持久化。使用DDD意味著我們要根據每個應用的需求來設計模型和實體,而且模型和實體是數據庫可忽略的,即可以使用任何數據庫技術實現保存。在這些情景中,我們應該使用EF的Code First方式,因為它允許我們創建POCO(Plain Old CLR Objects)作為持久化可忽略的領域模型。
使用Code First的優勢在于:
- 1、支持DDD。
- 2、可以早早地著手開發,因為我們不必等待數據庫的創建。
- 3、持久化層(底層的數據庫)的改變不會對現有的模型有任何影響。
我們需要搞清楚的第一件事就是約定大于配置的概念。Code First方式期望模型類遵守一些約定,這樣的話數據庫持久化邏輯就可以從模型中提取出來。比如,如果我們給一個模型定義了一個Id屬性,那么它就會映射到數據庫中該類所對應的那張表的主鍵。這種基于約定的方式的好處在于:如果我們遵守了這些約定,那么我們就不必寫額外的代碼來管理數據庫持久邏輯。但這樣也存在缺點,缺點在于:如果沒有遵守某個約定,那么EF就不會從模型中提取到需要的信息,運行時會拋異常。
在這種沒有遵守約定又要持久化數據的情況下,我們需要使用Code First的配置項提供關于模型一些額外的信息。比如,如果我們的模型類中沒有Id屬性作為主鍵,那么我們需要在想要的屬性上加上[Key]特性,這樣它就會被當作主鍵了。
注意:
EF使用模型類的復數的約定來創建數據表名,創建的列名和該類的屬性名是一樣的。
示例:
使用在EF應用一:Code First模式中介紹的使用方法創建一個數據庫,其中實體類Product定義如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace EFAppointmentCreateTable.Model { public class Product { public int Id { get; set; } public string ProductName { get; set; } public double ProductPrice { get; set; } } }
數據庫上下文Context類定義如下:
using EFAppointmentCreateTable.Model; using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Text; namespace EFAppointmentCreateTable.EFContext { ////// 定義數據庫上下文類,該類繼承自DbContext /// public class Context:DbContext { ////// 定義構造函數,繼承自父類的構造函數,通過繼承父類的構造函數來創建數據庫 /// 父類構造函數的參數是配置文件中配置的數據庫連接字符串 /// public Context() : base("DbConnection") { } //實體屬性集合 根據實體名稱的復數形式生成數據庫的表名 // 生成的表名是Products 和屬性名Products無關 // 即使把屬性名改成Product,生成的表名還是Products 約定大于配置 public DbSetProducts { get; set; } } }
創建后的數據庫截圖如下:
從上面的截圖中可以看出,生成的數據庫表名是實體Product的復數形式,使用默認約定生成Id主鍵列。
二、使用數據注解創建表結構
1、.NET數據類型和SQL數據類型之間的映射
首先EF這個ORM工具就是用來解決.NET類型和SQL Server列類型之間的阻抗失配的問題。比如,假設你在.net中定義了一個int類型的屬性,那么你就可以認為EF已經安全地處理了這個列的定義并使用了合適的類型與之對應。記住一些.NET類型和SQL Server列類型之間的映射是很有必要的,下面是一些最常用的映射關系:
SQL Server Database Type | .NET Type |
---|---|
Bigint | Int64 |
binary,varbinary | Byte[] |
Bit | Boolean |
date,datetime, datetime2,smalldatetime |
DateTime |
Datetimeoffset | DateTimeOffset |
decimal,money smallmoney,numeric |
Decimal |
float | Double |
int | Int32 |
nchar nvarchar,char varchar |
String |
real | Single |
rowversion,timestamp | Byte[] |
smallint | Int16 |
time | TimeSpan |
tinyint | Byte |
uniqueidentifier | Guid |
完整的映射列表可以參考SQL Server數據類型映射,如果你使用的是其他類型的數據庫,你可以在網上自行查找。比如,,如果是Oracle,那么你可以在這里查找:oracle數據類型映射。
2、配置原始屬性
以.NET中的string類型的屬性開始討論。SQL Server中的很多類型都會映射到.NET中的string類型,其他主流的RDBMS也是一樣的。因此,決定如何存儲字符串類型的信息是很重要的,很多關系數據庫管理引擎都有多個字符存儲類型,他們通常都有以字母N打頭的字符類型,這個字母表示要存在這些列中的數據是Unicode數據,基于每個字符以2個字節的格式存儲。因此,如果你的數據庫中的列存儲的是英文的話,就可以使用varchar或者char(可能會加速查詢),如果使用的是中文的話,就要使用nvarchar或者nchar。此外,還可以使用帶有var的字符類型來指定列的長度是可變的,不使用var的話,字符長度是不可變的。
在EF中有以下幾種配置數據庫結構的方式,分別是:
- 1、特性,也叫數據注解。
- 2、DbModelBuilder API。
- 3、配置伙伴類。
3、特性(數據注解)
這些特性類都是.NET的一部分,位于System.ComponentModel.DataAnnotaions命名空間下。下面我們修改在上一個例子中使用的Product實體類,修改后的Product實體類如下:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EFDataAnnotations.Model { ////// 使用Table特性指定生成的表名 /// [Table("Product")] public class Product { //使用Key特性指示該列是主鍵列 [Key] //使用Column特性指示生成的數據庫表中的列名 [Column("ID")] public int ProductId { get; set; } ////// StringLength設置數據庫表中列的長度 /// 指示ProductName字段的最大長度是10,最小長度是2 /// [StringLength(10,MinimumLength=2)] public string ProductName { get; set; } public double ProductPrice { get; set; } ////// DataType特性指示生成的數據庫表中列的數據類型 /// [DataType(DataType.DateTime)] public DateTime ProductionTime { get; set; } ////// NotMapped特性指示不把該屬性映射到數據庫表中,即在生成的表中沒有d這一列 /// [NotMapped] public decimal d { get; set; } } }
運行程序后生成的數據庫:
修改代碼之后,我們將表的名字使用Table特性全部重新命名成了但是,將Product的主鍵通過Column特性更改為Id,Key特性指定它是主鍵,還通過StringLength指定了ProductName列的最大長度為10個字符,最小為2個字符。
此外,數據注解也可以用作驗證特性。如果持久化數據時,模型對象的屬性值和數據注解所標記的不一致,就會拋異常。
數據驗證相關的數據注解:
特性 | 解釋 |
---|---|
Remote | 使用 jQuery 驗證插件遠程驗證程序的特性 |
FileExtension | 驗證文件擴展名 |
Compare | 比較兩個屬性的值 |
RegularExpression | 使用正則表達式驗證 |
CustomValidation | 自定義驗證方法 |
DataType | 指定要與數據字段關聯的附加類型的名稱 |
EmailAddress | 電子郵件地址(相當于DataType(DataType.Email)) |
Phone | 電話(相當于DataType(DataType.Phone)) |
CreditCard | 信用卡號碼(相當于DataType(DataType.CreditCard)) |
Url | 驗證URL(相當于DataType(DataType.Url)) |
MemberShipPassword | 驗證密碼字段是否滿足成員資格提供程序的當前密碼要求 |
數據映射相關的數據注解:
特性 | 解釋 |
---|---|
Key | 主鍵字段 |
Column | 數據庫列屬性映射 |
NotMapped | 不要創建對應的字段 |
Table | 指定類將映射到的數據庫表 |
ForeignKey | 表示關系中用作外鍵的屬性 |
DatabaseGenerated |
指定屬性應該映射到數據表中計算的列。也可以用于映射到自動增長的數據庫表。 指定數據庫生成屬性值的方式(EF不追蹤屬性的變化) |
Required | 必填字段 |
MaxLength | 指定屬性中允許的數組或字符串數據的最大長度 |
MinLength | 指定屬性中允許的數組或字符串數據的最小長度 |
StringLength | 指定最小和最大字符長度 |
Range | 指定數值范圍? |
數據顯示相關的數據注解:?
特性 | 解釋 |
---|---|
DisplayName | 指定本地化的字符串(習慣用語類) |
Display | 指定本地化的字符串(習慣用語屬性) |
DisplayFormat | 設置數據字段的格式 |
ReadOnly | 指定該特性所綁定到的屬性是只讀屬性還是讀/寫屬性 |
EditAble | 指示數據字段是否可編輯 |
HiddenInput | 指示是否應將屬性值或字段值呈現為隱藏的 input 元素 |
ScaffoldColumn | 指定類或數據列是否使用基架 |
UIHint | 指定動態數據用來顯示數據字段的模板 |
其他:
特性 | 解釋 |
---|---|
DisplayColumn | 將所引用的表中顯示的列指定為外鍵列 |
Description | 可視化設計器在引用組件成員時可以顯示指定的說明 (命名空間:System.ComponentModel.DescriptionAttribute) |
原文鏈接:https://www.cnblogs.com/dotnet261010/p/7417853.html
相關推薦
- 2022-10-16 QT網絡通信TCP客戶端實現詳解_C 語言
- 2022-05-25 C#多線程實現異步接口_C#教程
- 2022-07-13 nginx-1.20*安裝check模塊
- 2022-08-11 Go語言Grpc?Stream的實現_Golang
- 2022-08-26 C++類模板實戰之vector容器的實現_C 語言
- 2022-12-08 c++只保留float型的小數點后兩位問題_C 語言
- 2022-10-16 詳解C語言中結構體(struct)的用法_C 語言
- 2023-10-15 el-popover彈窗修改三角樣式或者位置
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支