[ORM] Entity Framework(2) CodeFirst進階

    在上一節中,實現了CodeFirst快速入門。可是不少與數據庫的細節還沒法自定義。以及使用EF過程當中,須要注意的事項。html

    在本節中,會涉及到如下sql

 

鏈接字符串數據庫

  1個完整的鏈接字符串  IP:端口\實例名 數據庫名組成併發

  Nuget安裝完EF會在*.config的entityFramework節點下添加,表示使用LocalDb數據庫,實例名爲v11.0。mvc

<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
</defaultConnectionFactory>

  而數據庫名,默認爲類的全限定名。以下調用父類構造函數,表示數據庫名爲SaleDb。而不是命名空間+類名。app

    public class SaleDb : DbContext
    {
        public SaleDb():base("SaleDb")
        {      
        }
    }

  固然,在這個構造函數裏,能夠完整的寫上完整的鏈接字符串。框架

 

EF的對象狀態異步

  db.Entry(TEntity).State  (附加Entity,並設置狀態)ide

    public enum EntityState
    {
        // 摘要: 
        //     The entity is not being tracked by the context.  An entity is in this state
        //     immediately after it has been created with the new operator or with one of
        //     the System.Data.Entity.DbSet Create methods.
        Detached = 1,
        //
        // 摘要: 
        //     The entity is being tracked by the context and exists in the database, and
        //     its property values have not changed from the values in the database.
        Unchanged = 2,
        //
        // 摘要: 
        //     The entity is being tracked by the context but does not yet exist in the
        //     database.
        Added = 4,
        //
        // 摘要: 
        //     The entity is being tracked by the context and exists in the database, but
        //     has been marked for deletion from the database the next time SaveChanges
        //     is called.
        Deleted = 8,
        //
        // 摘要: 
        //     The entity is being tracked by the context and exists in the database, and
        //     some or all of its property values have been modified.
        Modified = 16,
    }

  

延遲加載,貪婪加載,爲何須要Virtual函數

  延遲加載(lazy load)是(也稱爲懶加載),延遲加載機制是爲了不一些無謂的性能開銷而提出來的,所謂延遲加載就是當在真正須要數據的時候,才真正執行數據加載操做。能夠簡單理解爲,只有在使用的時候,纔會發出sql語句進行查詢。

  貪婪加載則是一次性把相關的表也加載進來。

在EF中,默認是支持延遲加載的。

  db.Configuration.LazyLoadingEnabled = false;    //設置禁用延遲加載

若是想單個貪婪加載某個表。則經過Include("表名")

  db.Orders.Include("OrderItems");          //把OrderItems表一併加載進來

 

Virtual關鍵字

一般相關連的表做爲Entity屬性的時候,使用Virtual關鍵字修飾符。若是不加Virtual關鍵字,則關聯的類只是一個普通的POCO類型。get,set方法爲空實現。

使用Virtual關鍵字後,EF生成一個代理類來重寫get和set方法。實現須要的功能。

  

繞過EF,直接SQL查詢

  EF做爲一個框架,也不可能作到知足全部需求。EF提供了直接操做Ado.net方式。

有三個 API 支持:

  • DbContext.Database.ExecuteSqlCommand
  • DbContext.Database.SqlQuery
  • DbSet.SqlQuery

         

執行sql 返回受影響函數。

public int ExecuteSqlCommand(string sql, params object[] parameters); 

 

執行sql 返回查詢結果並自動映射到指定類上。(不會被EF跟蹤狀態)

DbRawSqlQuery<TElement> SqlQuery<TElement>(string sql, params object[] parameters);

 

執行sql 返回查詢結果並自動映射到指定類上。(被EF跟蹤狀態。DbSqlQuery繼承自DbRawSqlQuery)

virtual DbSqlQuery<TEntity> SqlQuery(string sql, params object[] parameters);

 

查看EF生成SQL語句

  當使用EF執行一個複雜的查詢時候。咱們須要知道EF是否按照咱們所需執行。這時,就須要查看EF生成的語句。

  1. 執行IQueryable<T>.ToString(); 便可查看生成的sql語句。
  2. 經過EFProviderWrappers,這裏不作贅述。

 

DataAnnotation

  DataAnnotation 特性由.NET 3.5中引進,給.NET中的類提供了一種添加驗證的方式。同時在EF中,也是添加約束與個性化設置一種方式。

經常使用到如下特性。

  1. KeyAttribute:對應數據庫中的主鍵
  2. RequiredAttribute:對應數據庫中字段的數據是否能夠爲null
  3. MaxLengthAttribute:對應數據庫中字符串類型字段的最大長度
  4. MinLengthAttribute:在數據庫中無對應,但在代碼中字符串最小長度
  5. TimestampAttribute:將列的數據類型指定爲行版本
  6. DatabaseGeneratedAttribute:標記指定實體屬性是由數據庫生成的,並指定生成策略(None數據庫不生成值,Identity當插入行時,數據庫生成值,Computed當插入或更新行時,數據庫生成值)
  7. ColumnAttribute:指定實體屬性在數據庫中的列名及數據類型
  8. TableAttribute:指定實體類對應的數據表名
  9. ForeignKeyAttribute:指定導航屬性的外鍵字段
  10. NotMappedAttribute:標記指定實體屬性在建立數據庫中不建立對應字段
  11. ConcurrencyCheck:併發標記
    public class Order
    {
        [Key]
        public int Id { get; set; }
        [StringLength(200)]
        public string Name { get; set; }
        public int UserId { get; set; }
        [ForeignKey("UserId")]
        public User User { get; set; }
        public virtual ICollection<OrderItem> OrderItems { get; set; }
    }

  

 

FluentAPI

  使用DataAnnotation(DA)很是方便,但有時咱們的POCO類不但願受到EF的直接關聯。或者DA不能知足需求。這時,咱們可使用FluentAPI方式。

  1. HasKey - KeyAttribute:配置此實體類型的主鍵屬性
  2. IsRequired - RequiredAttribute:將此屬性配置爲必需屬性。用於存儲此屬性的數據庫列將不能夠爲null
  3. HasMaxLength - MaxLengthAttribute:將屬性配置爲具備指定的最大長度
  4. IsConcurrencyToken - ConcurrencyCheckAttribute:將屬性配置爲用做開放式併發標記
  5. IsRowVersion - TimestampAttribute:將屬性配置爲數據庫中的行版本。實際數據類型將因使用的數據庫提供程序而異。將屬性設置爲行版本會自動將屬性配置爲開放式併發標記。
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<AppInfo>().Property(o => o.Id).HasColumnName("AppId");
        }

  

MVC異步控制器作個CRUD例子

  微軟自家的東西關聯老是那麼方便。

在MVC5中,添加控制器的時候選擇使用EF即自動生成這一切。

 

 

建議

  1.模型改變從新生成數據庫,致使表數據丟失。

    在使用CodeFirst中,當模型改變的時候,採用第一節中的Nuget中EF Migration API方式則不會清空數據。

  2.是否使用存儲過程,視圖這些數據庫技術。

    當使用EF 這種ORM框架的時候,就應該輕數據庫技術,重業務邏輯層。個人建議是萬不得已不要使用存儲過程,視圖實際只是存儲了SQL語句。

 

MVC5代碼下載:MVCTest

相關文章
相關標籤/搜索