文件比較平常都是用Beyond Compare,可以說離不開的神器,特別是針對代碼比較這塊,確實挺好用的。 不過Beyond Compare平常拿它主要是用來做代碼比較,用來做一些大批量的二進位文件比較,其實有點不是很方便。 於是造輪子,重新寫了一個簡單的文件夾比較的小工具。 平常主要是拿來做一些N ...
Entity Framework (EF) Core 是輕量化、可擴展、開源和跨平臺版的常用 Entity Framework 數據訪問技術。
EF Core 可用作對象關係映射程式 (O/RM)
創建DbContext 對象
DbContext的生存期
DbContext 的生存期從創建實例時開始,併在釋放實例時結束。
DbContext生成
為每個請求創建一個 ApplicationDbContext 實例,並傳遞給控制器,以在請求結束後釋放前執行工作單元
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<ApplicationDbContext>(
options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));
}
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
public class MyController
{
private readonly ApplicationDbContext _context;
public MyController(ApplicationDbContext context)
{
_context = context;
}
}
public class ApplicationDbContext : DbContext
{
private readonly string _connectionString;
public ApplicationDbContext(string connectionString)
{
_connectionString = connectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_connectionString);
}
}
//或者
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
var contextOptions = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test")
.Options;
using var context = new ApplicationDbContext(contextOptions);
DBContext的屬性
所有DBContext配置的起始點都是 DbContextOptionsBuilder。 可以通過三種方式獲取此生成器:
- 在 AddDbContext 和相關方法中
- 在 OnConfiguring 中
- 使用 new 顯式構造
DbContextOptions
允許多個具體子類使用其不同的泛型 DbContextOptions 的實例初始化DBContext
public sealed class ApplicationDbContext1 : ApplicationDbContextBase
{
public ApplicationDbContext1(DbContextOptions<ApplicationDbContext1> contextOptions)
: base(contextOptions)
{
}
}
public sealed class ApplicationDbContext2 : ApplicationDbContextBase
{
public ApplicationDbContext2(DbContextOptions<ApplicationDbContext2> contextOptions)
: base(contextOptions)
{
}
}
protected ApplicationDbContext(DbContextOptions contextOptions)
: base(contextOptions)
{
}
DBContext的兩個關鍵方法
OnConfiguring配置方法
DBContext的配置入口
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//配置資料庫提供程式,還有其他資料庫配置如下圖:
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test");
//日誌記錄配置,通過在控制台輸出
optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information).EnableSensitiveDataLogging();
//關於其他DBContext配置,參看下圖
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder, typeof(BaseEntity));
}
關於其他資料庫提供程式
關於DbContextOptionsBuilder 的更多配置
OnModelCreating配置方法
實體的配置入口方法
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AuditEntry>();
}
使用 fluent API 配置模型替代OnModelCreating
關於實體的配置,還可使用Fluent api 可在上下文中替代 OnModelCreating 方法,並使用 Fluent API 來配置模型。 此配置方法最為有效,並可在不修改實體類的情況下指定配置。 Fluent API 配置具有最高優先順序,並將替代約定和數據註釋。 配置按調用方法的順序應用,如果存在任何衝突,最新調用將替代以前指定的配置。
查看代碼
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.IsRequired(); //代替修改實體
還有這種等等
[NotMapped]
public class BlogMetadata
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Ignore<BlogMetadata>();
}
DBContext的結構
模型
模型由實體類和表示資料庫會話的上下文對象構成。 上下文對象允許查詢並保存數據
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True");
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public int Rating { get; set; }
public List<Post> Posts { get; set; }
}
實體
在上下文中包含一種類型的 DbSet 意味著它包含在 EF Core 的模型中,或者在OnModelCreating 指定的;我們通常將此類類型稱為實體
加入實體的三種方式
- 在上下文的 DbSet 屬性中公開。
- 通過實體 Blog.Posts 的導航屬性發現的。
- 在 OnModelCreating 中指定的。
internal class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AuditEntry>();
}
}
public class Blog
{
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public string Content { get; set; }
}
實體的屬性約束
關於屬性的約束,查看一下鏈接 實體屬性 - EF Core | Microsoft Learn
以下列出常用
等等
|
|
[NotMapped]
|
|
[Column("blog_id")]
|
指定資料庫列映射,資料庫列與實體列不一致
|
[Column(TypeName = "varchar(200)")]
|
|
[MaxLength(500)]
|
|
[Required]
|
|
[Comment("The URL of the blog")]
|
描述
|
[Column(Order = 2)]
|
|
實體狀態變化規則
DBContext上下文為跟蹤狀態時,實體變化如下;
EntityState的5個狀態解釋:
成員名稱
|
說明
|
Detached
|
對象存在,但沒有被跟蹤。 在創建實體之後、但將其添加到對象上下文之前,該實體處於此狀態。 An entity is also in this state after it has been removed from the context by calling the Detach method or if it is loaded by using a NoTrackingMergeOption. 沒有 ObjectStateEntry 實例與狀態為 Detached 的對象關聯。
|
Unchanged
|
自對象附加到上下文中後,或自上次調用 SaveChanges 方法後,此對象尚未經過修改。
|
Added
|
對象為新對象,並且已添加到對象上下文,但尚未調用 SaveChanges 方法。 在保存更改後,對象狀態將更改為 Unchanged。 狀態為 Added 的對象在 ObjectStateEntry 中沒有原始值。
|
Modified
|
對象上的一個標量屬性已更改,但尚未調用 SaveChanges 方法。 在不帶更改跟蹤代理的 POCO 實體中,調用 DetectChanges 方法時,已修改屬性的狀態將更改為 Modified。 在保存更改後,對象狀態將更改為 Unchanged。
|
Deleted
|
刪除狀態
|
手動設置實體狀態
_mIPODataDBContext.Entry(t_TaskOrderFiles).Property(x => x.Url).IsModified = true;
_mIPODataDBContext.SaveChanges();
DBContext的查詢方式
跟蹤和不跟蹤查詢(AsNoTracking)
//跟蹤
var blog = context.Blogs.SingleOrDefault(b => b.BlogId == 1);
blog.Rating = 5;
context.SaveChanges();
//不跟蹤
var blogs = context.Blogs
.AsNoTracking()
.ToList();
//在上下文實例級別取消跟蹤
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
導航查詢(Include,ThenInclude)
//同級Include,子級,更深級別的關聯 ThenInclude
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList();
Inner Join查詢
通過linq表達式
var query = from photo in context.Set<PersonPhoto>()
join person in context.Set<Person>()
on new { Id = (int?)photo.PersonPhotoId, photo.Caption }
equals new { Id = person.PhotoId, Caption = "SN" }
where b.ProjectOrderId == Guid.Parse(proIdParam.Value) && p.IsDel == false
select new { person, photo };
SELECT [p].[PersonId], [p].[Name], [p].[PhotoId], [p0].[PersonPhotoId], [p0].[Caption], [p0].[Photo]
FROM [PersonPhoto] AS [p0]
INNER JOIN [Person] AS [p] ON ([p0].[PersonPhotoId] = [p].[PhotoId] AND ([p0].[Caption] = N'SN'))
通過lamada表達式
var query = from b in context.Set<Blog>()
from p in context.Set<Post>().Where(p => b.BlogId == p.BlogId)
select new { b, p };
SELECT [b].[BlogId], [b].[OwnerId], [b].[Rating], [b].[Url], [p].[PostId], [p].[AuthorId], [p].[BlogId], [p].[Content], [p].[Rating], [p].[Title]
FROM [Blogs] AS [b]
INNER JOIN [Posts] AS [p] ON [b].[BlogId] = [p].[BlogId]
Left Join查詢
lamada表達式
var query = from b in context.Set<Blog>()
join p in context.Set<Post>()
on b.BlogId equals p.BlogId into grouping
from p in grouping.DefaultIfEmpty()
select new { b, p };
linq表達式
var query2 = from b in context.Set<Blog>()
from p in context.Set<Post>().Where(p => b.BlogId == p.BlogId).DefaultIfEmpty()
select new { b, p };
SELECT [b].[BlogId], [b].[OwnerId], [b].[Rating], [b].[Url], [p].[PostId], [p].[AuthorId], [p].[BlogId], [p].[Content], [p].[Rating], [p].[Title]
FROM [Blogs] AS [b]
LEFT JOIN [Posts] AS [p] ON [b].[BlogId] = [p].[BlogId]
GroupJoin查詢
var query = from b in context.Set<Blog>()
join p in context.Set<Post>()
on b.BlogId equals p.BlogId into grouping
select new { b, Posts = grouping.Where(p => p.Content.Contains("EF")).ToList() };
GroupBy查詢
var query = from p in context.Set<Post>()
group p by p.AuthorId
into g
where g.Count() > 0
orderby g.Key
select new { g.Key, Count = g.Count() };
SELECT [p].[AuthorId] AS [Key], COUNT(*) AS [Count]
FROM [Posts] AS [p]
GROUP BY [p].[AuthorId]
HAVING COUNT(*) > 0
ORDER BY [p].[AuthorId]
支持的其他聚合運算符
.NET
|
SQL
|
Average(x => x.Property)
|
AVG(Property)
|
Count()
|
COUNT(*)
|
LongCount()
|
COUNT(*)
|
Max(x => x.Property)
|
MAX(Property)
|
Min(x => x.Property)
|
MIN(Property)
|
Sum(x => x.Property)
|
SUM(Property)
|
純SQL查詢
var rowsModified = context.Database.ExecuteSql($"UPDATE [Blogs] SET [Url] = NULL");
var overAverageIds = context.Database
.SqlQuery<int>($"SELECT [BlogId] AS [Value] FROM [Blogs]")
.Include(b => b.Posts)
.Where(id => id > context.Blogs.Average(b => b.BlogId))
.ToList();