主頁 > .NET開發 > EF 學習系列二 資料庫表的創建和表關系配置(Fluent API、Data Annotations、約定)

EF 學習系列二 資料庫表的創建和表關系配置(Fluent API、Data Annotations、約定)

2020-09-10 09:36:52 .NET開發

  上一篇寫了《Entity Farmework領域建模方式 3種編程方式》,現在就Code First 繼續學習

1、資料庫表的創建

新建一個MVC的專案,在參考右擊管理NuGet程式包,點擊瀏覽搜索EF安裝,我這里主要是EF6.0 以上的學習 所以都安裝6.0 以上的版本

 

 

 

 

接下來在Model檔案夾下面創建一個Customer類

 public class Customer    {        public int ID { get; set; }        public string Name { get; set; }        public int Age { get; set; }        public string Email { get; set; }        public DateTime AddTime { get; set; }    }

 

 

 

 

  在創建一個繼承EF背景關系的類XXDBContext,(個人習慣XX是我的名字拼音縮寫)此背景關系是資料庫互動的一個中間橋梁,我們稱之為會話,并且為為一個模型公開一個DbSet,默認情況下EF鏈接LocalDB本地資料庫(需要安裝LocalDB實體),我還是手動通過EF背景關系派生類的建構式來配置資料庫鏈接,下面我注釋的是資料庫初始化策略,我這里就選擇始終創建資料庫,后面用到配置表關聯與欄位的配置,

public class WYDBContext:DbContext    {        public WYDBContext(string ConnectionName) : base(ConnectionName) { }        public WYDBContext():base("SqlConn")        {            //默認的初始化器,這種初始化器在第一次運行程式時會創建資料庫,再次運行不會再創建新的資料庫,但是如果我們改變了領域類,運行程式時會拋出一個例外            //Database.SetInitializer(new CreateDatabaseIfNotExists<WYDBContext>());            //如果領域類發生了改變,洗掉以前的資料庫,然后重建一個新的,采用這種初始化器不用再擔心領域類改變影響資料庫架構的問題,            //Database.SetInitializer(new DropCreateDatabaseIfModelChanges<WYDBContext.cs>());            //每次運行程式都會洗掉以前的資料庫,重建新的資料庫,如果在開發程序中每次都想使用最新的資料庫,那么可以采用這種初始化器,            Database.SetInitializer(new DropCreateDatabaseAlways<WYDBContext>());            //禁用資料庫初始化策略            //Database.SetInitializer<WYDBContext>(null);        }        public DbSet<Customer> Customer { get; set; }    }

 

webconfig配置

<system.web>    <compilation debug="true" targetFramework="4.6.1" />    <httpRuntime targetFramework="4.6.1" />  </system.web>    <!--資料庫連接-->  <connectionStrings>    <!--資料庫連接ef字串-->    <add name="SqlConn" connectionString="Data Source=地址;Initial Catalog=資料庫名;Persist Security Info=True;User ID=用戶名;Password=密碼;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />  </connectionStrings>

 

現在如果直接啟動專案資料庫是不會被創建的,只有呼叫到才會創建,在Home控制器的Index中呼叫,啟動就生成了資料庫

public ActionResult Index()        {            using (var db =new  WYDBContext())            {                db.Customer.ToList();            }            return View();        }

 

 

 

 

2、 三者約定之 Code First約定(三者優先級 Fluent API > Data Annotations > 約定)

上面可已看出表Customer自己生成了主鍵ID,所謂約定,類似于C#中的介面,它是一個規范或者規則,使用Code First基于類定義通過約定來配置概念模型并以此為規則,約定就是基本規則,

Code First根據模型中定義的ID(不區分大小寫),或者是以類名加ID的屬性推斷這樣的屬性為ID,如果為int或者guid型別,那么主鍵映射成標識列(自增長),

Model下面在創建一個訂單Order類一個客戶有多個訂單一個訂單只能屬于某一個客戶這樣客戶與訂單的關系就是一對多

 public class Order    {        public int ID { get; set; }        public string Name { get; set; }        public decimal Price { get; set; }        public string Remark { get; set; }        public int CustomerID { get; set; }        /// <summary>        /// 訂單對應的客戶資訊        /// </summary>        public virtual Customer Customer { get; set; }    } public class Customer    {        public int ID { get; set; }        public string Name { get; set; }        public int Age { get; set; }        public string Email { get; set; }        public DateTime AddTime { get; set; }        /// <summary>        /// 客戶對應的訂單資訊        /// </summary>        public virtual IList<Order> Order { get; set; }    }

 

資料庫背景關系WYDBContext加上 public DbSet<Order> Order { get; set; } 剛剛加的訂單類,運行起來 如果資料庫洗掉不了的 自己閃一下 (在navicat 里面使用會這樣,我就換在SSMS里面用)

 

 

 

 

 

 

 它也生成了表與表的對應關系,然而string型別的你會發現欄位都是max這肯定不行,接下來看Data Annatations 配置

3、三者約定之 Data Annotations

Data Annotations我的理解就是在欄位類名上面加特性注解來控制欄位屬性的 栗子如下  還是Order與Customer兩張表 記得添加命名空間using System.ComponentModel.DataAnnotations;跟using System.ComponentModel.DataAnnotations.Schema;

 

public class Customer    {        /// <summary>        /// ID        /// </summary>        [Key]//標識次列為主鍵        [Column("Zj", Order = 0, TypeName = "int")]//列名Zj,資料庫序號0,型別int        [Required()]//不允許為空        [Display(Name = "Zj")]//顯示名稱,這里大多都是中文 后面視圖@Html.DisplayNameFor(item=> model.Name)用到 顯示的        public int Zj { get; set; }        /// <summary>        /// 姓名        /// </summary>        [Column("NameWYY", TypeName = "nvarchar")]//我加了WYY看效果        [StringLength(50, ErrorMessage = "{0}長度不能超過50個字符")]        [Display(Name = "姓名")]        public string Name { get; set; }        /// <summary>        /// 年齡        /// </summary>        [Column("Age", TypeName = "int")]        [Display(Name = "年齡")]        public int? Age { get; set; }//加了?允許為null        /// <summary>        /// 郵箱        /// </summary>        [Column("Email", TypeName = "nvarchar")]        [StringLength(50, ErrorMessage = "{0}長度不能超過50個字符")]        [Display(Name = "電子郵箱")]        public string Email { get; set; }        /// <summary>        /// 日期        /// </summary>        [Column("AddTime", TypeName = "datetime2")]//如果不定義datetime2添加DateTime.Now就會報錯哦        [Display(Name = "添加日期")]        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]//日期格式化        public DateTime AddTime { get; set; }        /// <summary>        /// 客戶對應的訂單資訊        /// </summary>        public virtual IList<Order> Order { get; set; }    }// [NotMapped]//表不映射到資料庫    [Table("Tb_Order")]//表名    public class Order    {        /// <summary>        /// ID        /// </summary>        [Key]        [Column("ID", Order = 0, TypeName = "int")]        [Required()]        [Display(Name = "ID")]        public int ID { get; set; }        /// <summary>        /// 名稱        /// </summary>        [Column("Name", TypeName = "nvarchar")]        [StringLength(50, ErrorMessage = "{0}長度不能超過50個字符")]        [Display(Name = "名稱")]        public string Name { get; set; }        /// <summary>        /// 價格        /// </summary>        [Column("Price")]        [Display(Name = "價格")]        public decimal? Price { get; set; }        /// <summary>        /// 備注        /// </summary>        [StringLength(3000)]//長度約束        [Column("Remark", TypeName = "nvarchar")]//我加了WYY看效果        [Display(Name = "備注")]        public string Remark { get; set; }        /// <summary>        /// 客戶ID        /// </summary>        [ForeignKey("Customer")]//外鍵         public int CustomerID { get; set; }        /// <summary>        /// 訂單對應的客戶資訊        /// </summary>        [ForeignKey("CustomerID")]//外鍵         public virtual Customer Customer { get; set; }        /// <summary>        /// 不映射欄位        /// </summary>        [NotMapped]//不映射到資料庫        public string XXX { get; set; }    }

 

 

 

 

 

 

 

4、三者約定之 Fluent API 

這個就要在派生類重寫OnModelCreating了  少一點 的表還可以在里面設定各個欄位多了還是映射Map在模型表里面寫,在OnModelCreatiing注冊模型類就可以了;

 public DbSet<Customer> Customer { get; set; }        public DbSet<Order> Order { get; set; }        protected override void OnModelCreating(DbModelBuilder modelBuilder)        {            //TODO 配置映射            modelBuilder.Entity<Customer>().ToTable("CSTo");//資料庫表名            modelBuilder.Entity<Customer>().HasKey(x => x.Zj);//主鍵            modelBuilder.Entity<Customer>().Property(x=>x.AddTime).HasColumnType("DATETIME2");//時間            modelBuilder.Entity<Customer>().Property(x=>x.Age).IsOptional();//為null            //HasColumnType("DATETIME2(7)")這種寫是錯的            modelBuilder.Entity<Customer>().Property(x => x.Name).IsRequired().HasColumnType("varchar").HasMaxLength(66);//不為空,型別,長度            //默認情況下不會生成復數的表  如Orders            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();            modelBuilder.Configurations.Add(new OrderMap());//注冊            base.OnModelCreating(modelBuilder);        }// [NotMapped]//表不映射到資料庫    [Table("Tb_Order")]//表名    public class Order    {        ///欄位            }    public class OrderMap : EntityTypeConfiguration<Order>    {        public OrderMap()        {            //對應資料庫表名            this.ToTable("ORd");            //一個訂單必須對應有一個客戶,客戶一對多(訂單)   用戶表里面的 CustomerID            this.HasRequired(p => p.Customer).WithMany(p => p.Order).HasForeignKey(p => p.CustomerID);            this.HasKey(k => k.ID);//主鍵            this.Property(p => p.Name).HasColumnType("VARCHAR").HasMaxLength(50).IsRequired();//Name欄位屬性(varchar,長度50,不為null)            this.Property(p => p.Remark).HasColumnType("VARCHAR").HasMaxLength(5000).IsOptional();//Remark(varchar,長度5000,null)            this.Property(p => p.Price).HasColumnName("pp");//列名        }    }

 

 

C#的數值型別對應資料庫如下

●C#中的 int型別默認映射后對應資料庫中的int型別,

● C#中的double型別默認映射后對應資料庫中的float型別

●C#中的float型別默認映射后對應資料庫中的real型別,

●C#中 的decimal型別默認映射后對應資料庫中的decimal(18,2)型別

●C#中 的Int64型別默認映射后對應資料庫中的bigint型別,

一般都是用Data Anntations  跟默認的約定好久沒用記錄一下  用到又來拿  Fluent API也是好久沒復習了 哈哈 有時間在看看書

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/1663.html

標籤:Entity Framework

上一篇:EFCore的外鍵級聯洗掉導致的【可能會導致回圈或多重級聯路徑】

下一篇:EF 學習系列三 資料操作資料加載及EF中執行Sql

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more