Entity Framework Core 2.0 新特性
一.模型級查詢過濾器(Model-level query filters)
ef core2.0包含了一個新特性,我們叫他模型級查詢過濾器(Model-level query filters)。此特性允許使用Linq查詢表達式直接定義在實體類型的元數據模型上。這樣的過濾器會自動應用到任何LINQ查詢所涉及的那些實體類型,包括間接引用的實體類型(對象引用,導航屬性)。這個特性的一些常見應用是:
軟刪除-定義一個?IsDeleted 屬性
多租戶-定義一個?TenantId 屬性
示例代碼:
public class BloggingContext : DbContext
{
? ? public DbSet<Blog> Blogs { get; set; }
? ? public DbSet<Post> Posts { get; set; }
? ? public int TenantId {get; set; }
? ? protected override void OnModelCreating(ModelBuilder modelBuilder)
? ? {
? ? ? ? modelBuilder.Entity<Post>().HasQueryFilter(
? ? ? ? ? ? p => !p.IsDeleted
? ? ? ? ? ? && p.TenantId == this.TenantId );
? ? }
}
我們給?Post?實體類型定義了一個模型級查詢過濾器,實現了多租戶和軟刪除。模型級過濾器將使用正確的上下文實例中的值,即執行查詢的那個。
使用??IgnoreQueryFilters()?方法在一次查詢中禁用過濾器。
局限性:
過濾器只能在層次結構的根實體類型上定義
過濾器不允許使用導航屬性進行過濾(可以根據反饋添加此功能。)
二.數據庫上下文池(DbContextPool)
這是兩種可選擇的性能特性之一,旨在在高并發場景中提供更好的性能支持。
在 ef core 2.0 中,我們將自定義的DbContext類型注冊到DbContextPool服務中,可讓該數據庫上下文類型的實例重復使用。
示例代碼:
services.AddDbContextPool<BloggingContext>(options => options.UseSqlServer(connectionString));如果使用這種方法,當一個控制器請求一個DbContext的實例時,首先會檢查是否在DbContextPool存在該類型的實例,當一次請求結束后,任何狀態的DbContext實例都會被重置,且將自身加入到DbContextPool中。
這在概念上類似于ADO.NET提供的數據庫連接池,旨在節省一些DbContext實例初始化的成本。
?
三.顯式編譯查詢(Explicitly compiled queries)
這是兩種可選擇的性能特性之二 。
在以前的ef版本中,調用查詢api時,可以通過自動編譯并緩存編譯的結果達到一次計算多次調用,有效的提高了ef的性能,顯示編譯查詢(Explicitly compiled queries)這種機制可以繞過緩存查找的性能消耗,直接調用已經編譯好的表達式,獲得一個小的性能提升。
示例代碼:
// Create an explicitly compiled query
private static Func<CustomerContext, int, Customer> _customerById =
? ? EF.CompileQuery((CustomerContext db, int id) =>
? ? ? ? db.Customers
? ? ? ? ? ? .Include(c => c.Address)
? ? ? ? ? ? .Single(c => c.Id == id));
// Use the compiled query by invoking it
using (var db = new CustomerContext())
{
? ?var customer = _customerById(db, 147);
}
四.在使用FromSql和ExecuteSqlCommand方法時加入參數化查詢
? 在使用C#6.0的特性構建SQL語句并使用FromSql和ExecuteSqlCommand方法執行SQL語句時,會自動加入使用參數化查詢,防止SQL注入。
示例代碼:
var city = "London";
var contactTitle = "Sales Representative";
using (var context = CreateContext())
{
? ? context.Set<Customer>()
? ? ? ? .FromSql($@"
? ? ? ? ? ? SELECT *
? ? ? ? ? ? FROM ""Customers""
? ? ? ? ? ? WHERE ""City"" = {city} AND
? ? ? ? ? ? ? ? ""ContactTitle"" = {contactTitle}")
? ? ? ? ? ? .ToArray();
? }
上面的代碼生成的SQL:
?
五.Attach can track a graph of new and existing entities
EF Core supports automatic generation of key values through a variety of mechanisms. When using this feature, a value is generated if the key property is the CLR default--usually zero or null. This means that a graph of entities can be passed to ?DbContext.Attach??or ?DbSet.Attach??and EF Core will mark those entities that have a key already set as Unchanged while those entities that do not have a key set will be marked as ?Added?. This makes it easy to attach a graph of mixed new and existing entities when using generated keys.??DbContext.Update? and ?DbSet.Update??work in the same way, except that entities with a key set are marked as??Modified? instead of ?Unchanged?.
?
六.表拆分(Table splitting)
現在可以將兩個或多個實體類型映射到同一表,其中主鍵列將被共享,每一行對應兩個或多個實體。
要使用表拆分,必須在共享表的所有實體類型之間配置標識關系(外鍵屬性構成主鍵)
示例代碼:
1 modelBuilder.Entity<Product>()2 .HasOne(e => e.Details).WithOne(e => e.Product)3 .HasForeignKey<ProductDetails>(e => e.Id);4 modelBuilder.Entity<Product>().ToTable("Products");5 modelBuilder.Entity<ProductDetails>().ToTable("Products");?
七.Owned types
一個owned實體類型可以與另一個owned實體類型共享相同的CLR類型。但是由于它不能被CLR類型識別,所以必須從另一個實體類型導航到它。包含定義導航的實體是所有者。當查詢所有者時,默認將包含所屬的類型。
按照慣例,將為所屬類型創建一個影子主鍵,它將通過使用表拆分映射到與所有者相同的表。
示例代碼:
modelBuilder.Entity<Order>().OwnsOne(p => p.OrderDetails, cb =>
? ? {
? ? ? ? cb.OwnsOne(c => c.BillingAddress);
? ? ? ? cb.OwnsOne(c => c.ShippingAddress);
? ? });
public class Order
{
? ? public int Id { get; set; }
? ? public OrderDetails OrderDetails { get; set; }
}
public class OrderDetails
{
? ? public StreetAddress BillingAddress { get; set; }
? ? public StreetAddress ShippingAddress { get; set; }
}
public class StreetAddress
{
? ? public string Street { get; set; }
? ? public string City { get; set; }
}
八.函數映射
EF支持映射數據庫中定義的函數,可以在LINQ查詢中使用。
需要在?DbContext?中定義一個靜態方法,并且使用?DbFunctionAttribute?特性。
示例代碼:
public class BloggingContext : DbContext
{
? ? [DbFunction]
? ? public static int PostReadCount(int blogId)
? ? {
? ? ? ? throw new Exception();
? ? }
}
這樣的方法是自動注冊。一旦注冊了方法,您就可以在查詢的任何地方使用它。
?要注意的幾件事:
按照慣例,在生成SQL時,該方法的名稱用作函數的名稱(在本例中是用戶定義的函數),但可以在方法注冊期間重寫名稱和schema。
目前只支持標量函數
EF Core遷移將不負責創建它,您必須在數據庫中創建映射函數
九.code first 實體配置
在EF6可以通過?EntityTypeConfiguraiton?封裝特定實體類型的配置代碼,在EF Core2.0中,這個特性回來了(EF Core 之前的 core版本不支持)。
示例代碼:
class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
? public void Configure(EntityTypeBuilder<Customer> builder)
? {
? ? ?builder.HasKey(c => c.AlternateKey);
? ? ?builder.Property(c => c.Name).HasMaxLength(200);
? ?}
}
...
// OnModelCreating
builder.ApplyConfiguration(new CustomerConfiguration());
十.Pluralization hook for DbContext Scaffolding
EF Core 2.0 introduces a new IPluralizer service that is used to singularize entity type names and pluralize DbSet names. The default implementation is a no-op, so this is just a hook where folks can easily plug in their own pluralizer.
Here is what it looks like for a developer to hook in their own pluralizer:
public class MyDesignTimeServices : IDesignTimeServices
{
? ? public void ConfigureDesignTimeServices(IServiceCollection services)
? ? {
? ? ? ? services.AddSingleton<IPluralizer, MyPluralizer>();
? ? }
}
public class MyPluralizer : IPluralizer
{
? ? public string Pluralize(string name)
? ? {
? ? ? ? return Inflector.Inflector.Pluralize(name) ?? name;
? ? }
? ? public string Singularize(string name)
? ? {
? ? ? ? return Inflector.Inflector.Singularize(name) ?? name;
? ? }
}
本人英語水平有限,如有翻譯不對的地方,歡迎批評指正。
原文地址:http://www.cnblogs.com/stulzq/p/7366044.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的Entity Framework Core 2.0 新特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET Core 2.0 的dll实时
- 下一篇: C#使用Xamarin开发可移植移动应用