從Nuget下載數據庫依賴
數據庫對應的依賴包:
貼幾個常用數據庫
-
SqlServer:Microsoft.EntityFrameworkCore.SqlServer (支持 SqlServer 2005 +)
-
Sqlite:Microsoft.EntityFrameworkCore.Sqlite
-
MySql:
-
MySql.EntityFrameworkCore:支持 (MySql 8.x +)
-
Pomelo.EntityFrameworkCore.MySql:(支持 MySql 5.x +)
-
配置Dbcontext
自己新建一個類繼承Dbcontext類(需引入命名空間 Microsoft.EntityFrameworkCore
)
此類必須具有DbContextOptions<ApplicationDbContext>
參數的公共構造函數 例如:
public class defaultDbcontext : DbContext
{
public defaultDbcontext(DbContextOptions<defaultDbcontext> options):base(options)
{
}
}
配置連接字符串
所有 DbContext
配置的起始點都是 DbContextOptionsBuilder
可以通過三種方式獲取此生成器:
-
在 AddDbContext 和相關方法中
通過依賴注入在 Startup 類中的 ConfigureServices方法中 使用 AddDbContext 方法配置
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<defaultDbcontext>(optin=> { optin.UseSqlite("data source=./blog.db"); }); }
-
在 OnConfiguring 中
重寫繼承類的
OnConfiguring
方法public class defaultDbcontext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.optin.UseSqlite("data source=./blog.db"); } }
這些
Use*
" 方法是由數據庫提供程序實現的擴展方法。 這意味着必須先安裝數據庫提供程序 NuGet 包,然后才能使用擴展方法。創建並模型
我個人理解就是根據實體生成數據庫並且配置數據庫各個字段(只是個人理解),說一下EFcore 是如何根據實體生成模型的具體可以參考
https://blog.csdn.net/catshitone/article/details/116595167
EFcore提供了兩種方式生成模型 一種是 fluent API 一種是 數據注釋 也就是特性 ,接下來分別演示下兩種方式配置使用 fluent API 配置模型
在我們剛剛創建的派生類
defaultDbcontext
中重寫OnModelCreating
方法,代碼如下protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<blog>(); //blod是實體類 還可以單獨配置實體的屬性 例如下面這句代碼 //modelBuilder.Entity<blog>().Property(x=>x.img).IsRequired(); 就表示img不能為空 更多的配置方法稍后貼個表格。 }
使用數據注釋方法(也叫特性)
public class blog { public int id { get; set; } public string titile { get; set; } public string img { get; set; } [Required] public string url { get; set; } public int Writerid { get; set; } public Writer Writer { get; set; } }
使用特性方式要在派生類
defaultDbcontext
中添加公開DbSet<Blog>
類型的屬性 讓EFcore 知道要根據哪個實體類生成模型。貼上完整代碼public class defaultDbcontext:DbContext { public defaultDbcontext(DbContextOptions<defaultDbcontext> options):base(options) { } public DbSet<blog> blogs; } public class blog { public int id { get; set; } public string titile { get; set; } public string img { get; set; } [Required] public string url { get; set; } public int Writerid { get; set; } public Writer Writer { get; set; } }
如果一個實體使用兩種方式配置 那么fluent API會替代特性方式
約定
這里貼上 官方文檔的說明:
按照約定,在上下文中的 DbSet 屬性中公開的類型作為實體包含在模型中。 還包括方法中指定的實體類型 OnModelCreating ,就像通過遞歸方式瀏覽其他發現的實體類型的導航屬性找到的任何類型一樣。
這句話什么意思呢 看官方給出的代碼
internal class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<AuditEntry>(); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } public Blog Blog { get; set; } } public class AuditEntry { public int AuditEntryId { get; set; } public string Username { get; set; } public string Action { get; set; } }
在上面的代碼中 因為實體Blod 在類型為
DbSet<Blog>
的屬性中所以它包含在模型中
而實體Post是實體Blod的導航屬性所在它包含在模型中
實體AuditEntry在OnModelCreating配置所在它包含在模型中實體的屬性約定
- 默認會把名字為id的屬性配置為主鍵,並且為自增長。
- 默認情況下屬性類型可為空對應的數據庫列可以為null,值類型對應的列不能為null
下面貼出常見約定
特性 | 應用范圍 | 功能 | FluentAPI |
---|---|---|---|
[NotMapped] |
類或屬性 | 在模型中排除此類或此屬性的映射 | modelBuilder.Ignore<BlogMetadata>(); modelBuilder.Entity<Blog>().Ignore(b => b.LoadedFromDatabase); |
[Table("xxx")] |
類 | 設置這個類對應的數據庫表名,默認表名是DbSet<T> 的屬性名 |
modelBuilder.Entity<Blog>().ToTable("blogs"); |
[Table("xxx", Schema = "blogging")] * |
類 | 用來設置映射的表架構,默認的架構是dbo | modelBuilder.Entity<Blog>().ToTable("blogs", schema: "blogging") ; |
[Column("xxx")] |
屬性 | 用來設置要映射的列名 | modelBuilder.Entity<Blog>().Property(b => b.BlogId).HasColumnName("blog_id"); |
[Column(TypeName="varchar(200)")] |
屬性 | 用來設置列的數據類型 默認情況下 DateTime 會映射為datetime2(7) ,string 映射到nvarchar(max) 或nvarchar(450) |
modelBuilder.Entity<Blog>(eb =>{eb.Property(b => b.Url).HasColumnType("varchar(200)");eb.Property(b => b.Rating).HasColumnType("decimal(5, 2)");}); |
- | - | 映射到數據庫視圖 | modelBuilder.Entity<Blog>().ToView("blogsView", schema: "blogging"); |
- | - | 映射到表值函數(TVF[) | 鏈接 |
[Comment("xxxx")] |
類或屬性 | 表或列的注釋 | modelBuilder.Entity<Blog>().HasComment("xxxx"); modelBuilder.Entity<Blog>().Property(b => b.Url).HasComment("The URL of the blog"); |
[MaxLength(500)] |
屬性 | 設置最大長度,適用於數組數據類型,如string 和byte[] |
modelBuilder.Entity<Blog>().Property(b => b.Url).HasMaxLength(500); |
- | - | 設置精度和小數位 通常為 decimal 或DateTime 類型的屬性 |
modelBuilder.Entity<Blog>().Property(b => b.Score).HasPrecision(14, 2);modelBuilder.Entity<Blog>().Property(b => b.LastUpdated).HasPrecision(3); |
[Required] |
屬性 | 設置列為非空 默認情況下可空類型對應的列可以為null,值類型不為null |
modelBuilder.Entity<Blog>().Property(b => b.Url).IsRequired(); |
[Key] |
屬性 | 設置主鍵 | modelBuilder.Entity<Car>().HasKey(c => c.LicensePlate); 1.這個特性沒法應用到復合主鍵上,但是可以通過FluentAPI的方式: modelBuilder.Entity<Car>().HasKey(c => new { c.State, c.LicensePlate }); 2.設置主鍵名稱 modelBuilder.Entity<Blog>().HasKey(b => b.BlogId).HasName("PrimaryKey_BlogId"); ,默認名稱是PK_<type name> |
[Index(nameof(Url),Name="Index_Url")] ** |
類 | 給實體的Url屬性對應的列上設置索引,並指定索引的名稱 | modelBuilder.Entity<Blog>().HasIndex(b => b.Url).HasDatabaseName("Index_Url"); |
[Index(nameof(FirstName), nameof(LastName))] |
類 | 設置復合索引 | modelBuilder.Entity<Person>().HasIndex(p => new { p.FirstName, p.LastName }); |
[Index(nameof(Url), IsUnique = true)] |
類 | 設置唯一索引 | modelBuilder.Entity<Blog>().HasIndex(b => b.Url).IsUnique(); |
[Keyless] |
類 | 設置此實體里沒有主鍵,框架不會對此實體的狀態進行跟蹤,即使有更改也不會保存到數據庫中 | modelBuilder.Entity<Blog>().HasNoKey(); |
**:默認的索引名稱是IX_<type name>_<property name>
最后說下遷移
遷移需要安裝工具包Microsoft.EntityFrameworkCore.Tools
安裝完成后在Nuget控制台運行添加遷移命令 Add-Migration init
init是遷移名稱,可隨意。 在運行 Update-Database init
應用遷移將所做更改應用到數據庫。