EF Core 筆記


回滾最近的一次遷移記錄

remove-migration    會報錯

加參數remove-migration --force 

 

一個程序集下面存在多個DbContext   指定DbContext進行遷移

add-migration --context XXXDbContext

 

一個事務中    先在數據庫查出一條數據進行修改      然后在進行查詢  他會直接在內存中找到這條數據  不會再數據庫查詢了

EF Core的 linq語句中可以使用C#方法或函數   在EF6或之前版本不可以

 

 

 

.Include()  在EF Core和 EF6中支持lamada表達式  之前的版本該方法只接受列名字符串

 

 使用原生sql

 FormSql已棄用

        using (var dataContext = new SampleDbContext()) {
        
            var query = dataContext.Categories.FromSqlRaw("select * from Category");

            var result = query.ToList();
        }

通過這種方式拼接sql  會自動拼接成帶參數的sql語句

 var query = dataContext.Categories.FromSql($"select * from Category where CategoryID={categoryID}");

執行存儲過程

 var query = dataContext.Categories.FromSql($"GetCategoryById {categoryID}");

 

 

配置一對一關系   在EF6.X或之前不支持     

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
       
    public StudentAddress Address { get; set; }
}

public class StudentAddress
{
    public int StudentAddressId { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public int StudentId { get; set; }
    public Student Student { get; set; }
}

在Student表中自動產生一個AddressId列    

   訂單行關聯訂單頭可以省略前兩行代碼     直接寫最后一行

    public class SalesOrderLine : Entity<Guid>
    {
        /// <summary>
        /// 銷售訂單ID
        /// </summary>
        public virtual Guid? SalesOrderId { set; get; }
        /// <summary>
        /// 銷售訂單
        /// </summary>
        [ForeignKey(nameof(SalesOrderId))]
        public virtual SalesOrder SalesOrder { set; get; }

 

EF中已經有了默認的約定來實現一對多  如果想要自己寫 可以擴展 Fluent API    這些一對多的配置在EF約定中就已經實現了  不需要自己配置    可以通過這個配置來實現級聯刪除

            //配置訂單頭實體和訂單行實體的關系
            modelBuilder.Entity<SalesOrder>()
                //訂單頭實體對象包含了 多個的訂單行
                .HasMany<SalesOrderLine>(t => t.Lines)
                //訂單行實體對象包含了 唯一的個訂單頭
                .WithOne(g => g.SalesOrder)
                //通過行的SalesOrderId屬性進行關聯
                .HasForeignKey(g => g.SalesOrderId);

            //反過來配置
            modelBuilder.Entity<SalesOrderLine>()
                //訂單行實體對象包含了 唯一的訂單頭
                .HasOne<SalesOrder>(t => t.SalesOrder)
                //訂單頭實體對象包含了 多個訂單行
                .WithMany(g => g.Lines)
                //通過行的SalesOrderId屬性進行關聯
                .HasForeignKey(t => t.SalesOrderId);

 級聯刪除

            //級聯刪除
            //前面的配置都一樣   只要在最后加上OnDelete
            modelBuilder.Entity<SalesOrder>()
                .HasMany<SalesOrderLine>(t => t.Lines)
                .WithOne(g => g.SalesOrder)
                .HasForeignKey(g => g.SalesOrderId)
                .OnDelete(DeleteBehavior.Cascade);
            //Cascade  刪除主實體時將刪除從屬實體
            //ClientSetNull 刪除主實體時將從屬實體的的外鍵屬性值設置為null
            //Restrict  防止級聯刪除
            //SetNull   刪除主實體時將從屬實體的的外鍵屬性值設置為null

 多對多的關系只能自己配置

 Entity Framework Core中沒有可自動配置多對多關系的默認約定。您必須使用Fluent API對其進行配置。 

學生表
public
class Student { public int StudentId { get; set; } public string Name { get; set; } public IList<StudentCourse> StudentCourses { get; set; } } 課程表 public class Course { public int CourseId { get; set; } public string CourseName { get; set; } public string Description { get; set; } public IList<StudentCourse> StudentCourses { get; set; } }
//通過一張中間表來實現學生跟課程的多對多關系
public
class StudentCourse { public int StudentId { get; set; } public Student Student { get; set; } public int CourseId { get; set; } public Course Course { get; set; } }
關系配置
modelBuilder.Entity<StudentCourse>().HasKey(sc => new { sc.StudentId, sc.CourseId });

 獲取當前跟蹤的所有實體

context.ChangeTracker.Entries()

 

可以使用 FromSql 擴展方法基於原生 SQL 查詢開始 LINQ 查詢。

var blogs = context.Blogs
    .FromSql("SELECT * FROM dbo.Blogs")
    .ToList();

原生 SQL 查詢可用於執行存儲過程。

var blogs = context.Blogs
    .FromSql("EXECUTE dbo.GetMostPopularBlogs")
    .ToList();

 

 單獨配置給某一個實體添加租戶過濾和軟刪除過濾

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>().Property<string>("TenantId").HasField("_tenantId");

    // Configure entity filters
    modelBuilder.Entity<Blog>().HasQueryFilter(b => EF.Property<string>(b, "TenantId") == _tenantId);
    modelBuilder.Entity<Post>().HasQueryFilter(p => !p.IsDeleted);
}

 

指定當前實體框架Linq查詢不應用任何模型級實體查詢篩選器。 不應用配置的軟刪除過濾和租戶過濾 

blogs = db.Blogs
    .Include(b => b.Posts)
    .IgnoreQueryFilters()
    .ToList();

 

 

 

 程序和數據庫中對應類型

 

 

關於在ABP中 是否手動寫await customerRepository.UpdateAsync(cc); 更新這行代碼的測試     (不寫EF會自動監測到所有修改的字段  進行更新 ,  寫了會更新所有字段)

1.不寫這行代碼  讓事務自動提交

  在數據庫監控日志中會產生兩條sql語句記錄    一條是查詢  一條是更新  更新的語句只更新修改過的字段

2.寫了這行代碼

  在數據庫監控日志中只有一條sql語句記錄  查詢和更新是在一起的  但是更新了所有字段

 

關於ef的遷移文件

add-migration   通過對比DBContext中的實體和總快照文件來生成遷移文件  

update-database  會查詢__EFMigrationsHistory表中的遷移記錄  知道了最后一次遷移記錄   把這次一次之后的所有遷移文件都執行一遍

ModelSnapshot遷移快照文件   每次通過add-migration生成新的遷移文件的時候  會對比dbContext中的實體跟快照中的記錄   以這個為標准來產生新的遷移文件

遷移文件 :通過對比DBContext中的實體和快照文件來生成遷移文件  

  當前遷移文件中有兩個方法:一個是Up  Up就是使用update-database是執行的代碼段       Down是回滾遷移文件執行的代碼段     Up跟Down的的代碼段肯定是相反的      比如在Up中新增一張表    在Down中就是刪除這張表

遷移文件下面還有一個.Designer的文件    執行當前遷移文件后的快照文件

 

創建新庫的時候: 因為不存在遷移記錄表  所以會把所有遷移文件按順序執行一遍    如果有丟失的遷移文件  則可能報錯  遷移失敗

修改庫:找到當前遷移表中記錄的遷移文件  執行在這之后新增的所有遷移文件

 

自動遷移

dbContext.Database.EnsureCreated();//不存在數據庫則執行遷移  不執行更新操作

dbContext.Database.Migrate();每次都執行遷移文件  有最新就更新

https://docs.microsoft.com/zh-cn/ef/core/saving/cascade-delete

http://www.entityframeworktutorial.net/efcore/querying-in-ef-core.aspx


免責聲明!

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



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