Nowe funkcje w programie EF Core 2.0New features in EF Core 2.0

.NET 2.0 standardowe.NET Standard 2.0

Podstawowe EF dotyczy teraz .NET Standard 2.0, co oznacza, że może współpracować z .NET Core 2.0, .NET Framework 4.6.1 i innych bibliotek, które implementuje standardowe .NET w wersji 2.0.EF Core now targets .NET Standard 2.0, which means it can work with .NET Core 2.0, .NET Framework 4.6.1, and other libraries that implement .NET Standard 2.0. Zobacz obsługiwane implementacje .NET uzyskać więcej informacji dotyczących co jest obsługiwane.See Supported .NET Implementations for more details on what is supported.

ModelowanieModeling

Dzielenie tabeliTable splitting

Obecnie istnieje możliwość zamapować co najmniej dwa typy jednostek do tej samej tabeli, w którym będą udostępniane z kolumn klucza podstawowego i każdy wiersz odpowiada dwóch lub więcej jednostek.It is now possible to map two or more entity types to the same table where the primary key column(s) will be shared and each row will correspond to two or more entities.

Aby tabeli dzielenia relacji identyfikującej (w którym właściwości klucza obcego tworzą klucza podstawowego) musi być skonfigurowany między wszystkie typy jednostek, udostępnianie w tabeli:To use table splitting an identifying relationship (where foreign key properties form the primary key) must be configured between all of the entity types sharing the table:

modelBuilder.Entity<Product>()
    .HasOne(e => e.Details).WithOne(e => e.Product)
    .HasForeignKey<ProductDetails>(e => e.Id);
modelBuilder.Entity<Product>().ToTable("Products");
modelBuilder.Entity<ProductDetails>().ToTable("Products");

Typy należące do firmyOwned types

Typ jednostki należące do firmy mogą udostępniać tego samego typu CLR z innym typem należących do jednostki, ale ponieważ nie można zidentyfikować przez typ CLR musi istnieć nawigację do niego z innego typu jednostki.An owned entity type can share the same CLR type with another owned entity type, but since it cannot be identified just by the CLR type there must be a navigation to it from another entity type. Obiekt zawierający definiującego nawigacji jest właścicielem.The entity containing the defining navigation is the owner. Podczas wykonywania zapytania właściciela należących do typów zostaną uwzględnione domyślnie.When querying the owner the owned types will be included by default.

Konwencja klucz podstawowy w tle zostanie utworzona dla typu należące do firmy i będzie on zamapowany do tej samej tabeli jako właściciel przy użyciu dzielenia tabeli.By convention a shadow primary key will be created for the owned type and it will be mapped to the same table as the owner by using table splitting. Dzięki temu Użyj należące do typów podobnie jak złożonych typów są używane w EF6:This allows to use owned types similarly to how complex types are used in EF6:

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; }
}

Filtry kwerendy na poziomie modeluModel-level query filters

Podstawowe EF 2.0 zawiera nową funkcję nazywamy filtrów kwerendy na poziomie modelu.EF Core 2.0 includes a new feature we call Model-level query filters. Ta funkcja umożliwia predykaty zapytań LINQ (wyrażenia logicznego zwykle przekazane do operatora zapytania LINQ gdzie) należy zdefiniować bezpośrednio na typy jednostek w modelu metadanych (zwykle w OnModelCreating).This feature allows LINQ query predicates (a boolean expression typically passed to the LINQ Where query operator) to be defined directly on Entity Types in the metadata model (usually in OnModelCreating). Takie filtry są automatycznie stosowane do wszelkich zapytań LINQ tych typów jednostek, w tym odwołań do właściwości nawigacji do którego istnieje odwołanie pośrednie, takie jak przy użyciu Include lub bezpośredniego typów jednostek.Such filters are automatically applied to any LINQ queries involving those Entity Types, including Entity Types referenced indirectly, such as through the use of Include or direct navigation property references. Niektóre typowe zastosowania tej funkcji są następujące:Some common applications of this feature are:

  • Usuń soft - typów jednostek definiuje właściwość IsDeleted.Soft delete - An Entity Types defines an IsDeleted property.
  • Wielodostępność — typ jednostki definiuje właściwość identyfikatora dzierżawcy.Multi-tenancy - An Entity Type defines a TenantId property.

Poniżej przedstawiono prosty przykład prezentacja funkcji w dwóch scenariuszach wymienione powyżej:Here is a simple example demonstrating the feature for the two scenarios listed above:

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 );
    }
}

Definicję filtru na poziomie modelu, który implementuje obsługi wielu dzierżawców i soft usunięcie wystąpienia Post typu jednostki.We define a model-level filter that implements multi-tenancy and soft-delete for instances of the Post Entity Type. Zwróć uwagę na użycie właściwości poziomu wystąpienia typu DbContext: TenantId.Note the use of a DbContext instance level property: TenantId. Filtry na poziomie modelu użyje wartości z wystąpienia poprawny kontekst.Model-level filters will use the value from the correct context instance. Tj. ten, który wykonuje zapytania.I.e. the one that is executing the query.

Filtry mogą być wyłączone dla poszczególnych zapytań LINQ za pomocą operatora IgnoreQueryFilters().Filters may be disabled for individual LINQ queries using the IgnoreQueryFilters() operator.

OgraniczeniaLimitations

  • Odwołania nawigacji nie są dozwolone.Navigation references are not allowed. Ta funkcja może być dodany oparte na opinii.This feature may be added based on feedback.
  • Filtry można zdefiniować tylko w katalogu głównym typu jednostki z hierarchii.Filters can only be defined on the root Entity Type of a hierarchy.

Mapowanie funkcji skalarnych bazy danychDatabase scalar function mapping

Wersja zapoznawcza 2 zawiera ważne wkładu Middleton Pawła co pozwala mapowania funkcji skalarnych bazy danych do metody zastępcze, dzięki czemu mogą być używane w zapytaniach LINQ i przetłumaczyć na język SQL.Preview 2 includes an important contribution from Paul Middleton which enables mapping database scalar functions to method stubs so that they can be used in LINQ queries and translated to SQL.

Poniżej przedstawiono krótki opis sposobu użycia funkcji:Here is a brief description of how the feature can be used:

Deklaruje metody statycznej na Twojej DbContext i adnotacje go przy użyciu DbFunctionAttribute:Declare a static method on your DbContext and annotate it with DbFunctionAttribute:

public class BloggingContext : DbContext
{
    [DbFunction]
    public static int PostReadCount(int blogId)
    {
        throw new Exception();
    }
}

Metody, takie jak to automatycznie są rejestrowane.Methods like this are automatically registered. Gdy zarejestrowano metody umożliwia dowolnym zapytania:Once a method has been registered you can use it anywhere in your queries:

var query =
    from p in context.Posts
    where BloggingContext.PostReadCount(p.Id) > 5
    select p;

Kilka rzeczy do uwzględnienia:A few things to note:

  • Konwencja Nazwa metody jest używana jako nazwa funkcji (w tym przypadku funkcja zdefiniowana przez użytkownika) podczas generowania SQL, ale można zastąpić nazwę i schematu podczas rejestracji — metodaBy convention the name of the method is used as the name of a function (in this case a user defined function) when generating the SQL, but you can override the name and schema during method registration
  • Obecnie obsługiwane są tylko funkcje skalarneCurrently only scalar functions are supported
  • Funkcja mapowane należy utworzyć w bazie danych, np. Core EF migracji nie zajmie się jej tworzeniaYou must create the mapped function in the database, e.g. EF Core migrations will not take care of creating it

Konfiguracja niezależne typu dla kodu pierwszySelf-contained type configuration for code first

W EF6 było możliwe Hermetyzowanie kod pierwszego konfiguracji określonego typu przez wynikających z typu EntityTypeConfiguration.In EF6 it was possible to encapsulate the code first configuration of a specific entity type by deriving from EntityTypeConfiguration. W programie EF Core 2.0 możemy są dostarczają tego wzorca ponownie:In EF Core 2.0 we are bringing this pattern back:

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());

Wysoka wydajnośćHigh Performance

Buforowanie typu DbContextDbContext pooling

Podstawowy wzorzec używania EF Core w aplikacji platformy ASP.NET Core zwykle obejmuje rejestrowania niestandardowego typu DbContext w systemie iniekcji zależności i później uzyskiwania wystąpień tego typu za pomocą parametrów konstruktora kontrolery.The basic pattern for using EF Core in an ASP.NET Core application usually involves registering a custom DbContext type into the dependency injection system and later obtaining instances of that type through constructor parameters in controllers. Oznacza to, że nowe wystąpienie klasy DbContext jest tworzony dla każdego żądania.This means a new instance of the DbContext is created for each requests.

W wersji 2.0 wprowadzamy nowy sposób rejestrowania niestandardowego typu DbContext w iniekcji zależności, które prezentuje sposób niewidoczny dla użytkownika puli wielokrotnego użytku wystąpienia typu DbContext.In version 2.0 we are introducing a new way to register custom DbContext types in dependency injection which transparently introduces a pool of reusable DbContext instances. Aby korzystać z pul DbContext, użyj AddDbContextPool zamiast AddDbContext podczas rejestracji usługi:To use DbContext pooling, use the AddDbContextPool instead of AddDbContext during service registration:

services.AddDbContextPool<BloggingContext>(
    options => options.UseSqlServer(connectionString));

Jeśli ta metoda jest używana, w tym czasie wystąpienie typu DbContext jest wymagany przez kontrolera się, że firma Microsoft będzie najpierw sprawdź, czy wystąpienie dostępne w puli.If this method is used, at the time a DbContext instance is requested by a controller we will first check if there is an instance available in the pool. Po Kończenie znajdujących się przetwarzanie żądania, każdy stan w wystąpieniu jest resetowany, a wystąpienie jest zwrócony do puli.Once the request processing finalizes, any state on the instance is reset and the instance is itself returned to the pool.

To jest podobny do sposobu użycia puli połączeń działa w dostawcy ADO.NET i daje możliwość zapisywania koszt inicjowania wystąpienie typu DbContext.This is conceptually similar to how connection pooling operates in ADO.NET providers and has the advantage of saving some of the cost of initialization of DbContext instance.

OgraniczeniaLimitations

Nowa metoda wprowadzono kilka ograniczenia co można zrobić OnConfiguring() metody DbContext.The new method introduces a few limitations on what can be done in the OnConfiguring() method of the DbContext.

Ostrzeżenie

Unikaj przy użyciu buforowania DbContext, jeśli obsługa własne stanu (np. pola prywatne) w klasie pochodnej DbContext, który nie powinien być współużytkowane przez wiele żądań.Avoid using DbContext Pooling if you maintain your own state (e.g. private fields) in your derived DbContext class that should not be shared across requests. Podstawowe EF tylko spowoduje zresetowanie stanu, który zna przed dodaniem wystąpienie typu DbContext do puli.EF Core will only reset the state that is aware of before adding a DbContext instance to the pool.

Jawnie skompilowane zapytaniaExplicitly compiled queries

Jest to drugi zdecydować się na wydajności funkcje oferują korzyści w scenariuszach wysokiej skali.This is the second opt-in performance features designed to offer benefits in high-scale scenarios.

Ręczne lub jawnie skompilowanego zapytania zostały dostępne w poprzednich wersjach programu EF, a także w składniku LINQ to SQL, aby umożliwić aplikacjom pamięci podręcznej w tłumaczeniu wartości zapytania, aby tylko jeden raz obliczana interfejsów API i wykonywane wiele razy.Manual or explicitly compiled query APIs have been available in previous versions of EF and also in LINQ to SQL to allow applications to cache the translation of queries so that they can be computed only once and executed many times.

Ogólnie rzecz biorąc automatycznie EF Core skompilować i pamięci podręcznej zapytania oparte na mieszanych reprezentacja wyrażenia zapytania, ten mechanizm może służyć do uzyskania bardziej wydajne małych pomijając obliczania skrótu i wyszukiwania w pamięci podręcznej, dzięki czemu aplikacji do korzystania z już skompilowane zapytania za pomocą wywołania delegata.Although in general EF Core can automatically compile and cache queries based on a hashed representation of the query expressions, this mechanism can be used to obtain a small performance gain by bypassing the computation of the hash and the cache lookup, allowing the application to use an already compiled query through the invocation of a delegate.

// 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);
}

Śledzenie zmianChange Tracking

Dołącz można śledzić wykres nowych i istniejących jednostekAttach can track a graph of new and existing entities

Jądro EF obsługuje automatyczne generowanie wartości klucza przy użyciu różnych mechanizmów.EF Core supports automatic generation of key values through a variety of mechanisms. Podczas używania tej funkcji, wartość jest generowany, gdy właściwość klucza jest domyślnym CLR — zwykle zero lub wartość null.When using this feature, a value is generated if the key property is the CLR default--usually zero or null. Oznacza to, że wykres jednostek mogą zostać przekazane do DbContext.Attach lub DbSet.Attach i EF Core spowoduje oznaczenie tych obiektów, które mają klucz, który został już ustawiony jako Unchanged podczas tych jednostek, które nie mają ustawionego klucza zostaną oznaczone jako Added.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. Ułatwia dołączyć wykres mieszany nowych i istniejących obiektów przy użyciu generowane kluczy.This makes it easy to attach a graph of mixed new and existing entities when using generated keys. DbContext.Updatei DbSet.Update działa w taki sam sposób, z tą różnicą, że jednostki z zestawu kluczy są oznaczone jako Modified zamiast Unchanged.DbContext.Update and DbSet.Update work in the same way, except that entities with a key set are marked as Modified instead of Unchanged.

ZapytanieQuery

Tłumaczenie ulepszone LINQImproved LINQ Translation

Włącza więcej zapytania, aby pomyślnie wykonać z logiką więcej oceniane w bazie danych (a nie w pamięci) i mniejsza ilość danych niepotrzebnie pobrane z bazy danych.Enables more queries to successfully execute, with more logic being evaluated in the database (rather than in-memory) and less data unnecessarily being retrieved from the database.

Ulepszenia GroupJoinGroupJoin improvements

Praca ta poprawia SQL Server, który jest generowany dla grupy sprzężeń.This work improves the SQL that is generated for group joins. Sprzężenia grupowane najczęściej są wynikiem podzapytaniach dla właściwości nawigacji opcjonalne.Group joins are most often a result of sub-queries on optional navigation properties.

Ciąg interpolacji FromSql i ExecuteSqlCommandString interpolation in FromSql and ExecuteSqlCommand

C# 6 wprowadzony ciąg interpolacji, funkcja, która umożliwia wyrażeń C# bezpośrednio osadzone w literałach ciągu, dzięki czemu nieuprzywilejowany budynku ciągów w czasie wykonywania.C# 6 introduced String Interpolation, a feature that allows C# expressions to be directly embedded in string literals, providing a nice way of building strings at runtime. W programie EF Core 2.0 dodaliśmy specjalne obsługę ciągi interpolowane do naszych dwa podstawowe interfejsów API akceptujących raw ciągów SQL: FromSql i ExecuteSqlCommand.In EF Core 2.0 we added special support for interpolated strings to our two primary APIs that accept raw SQL strings: FromSql and ExecuteSqlCommand. Ta nowa funkcja obsługi umożliwia C# interpolacji ciąg do użycia w sposób "bezpiecznym".This new support allows C# string interpolation to be used in a 'safe' manner. Np. w sposób zapewniający ochronę przed typowych pomyłek iniekcji kodu SQL, które mogą wystąpić podczas dynamiczne budowanie SQL w czasie wykonywania.I.e. in a way that protects against common SQL injection mistakes that can occur when dynamically constructing SQL at runtime.

Oto przykład:Here is an example:

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();
  }

W tym przykładzie istnieją dwie zmienne osadzone w formacie ciągu SQL.In this example, there are two variables embedded in the SQL format string. Podstawowe EF utworzy następujące instrukcje SQL:EF Core will produce the following SQL:

@p0='London' (Size = 4000)
@p1='Sales Representative' (Size = 4000)

SELECT *
FROM ""Customers""
WHERE ""City"" = @p0
    AND ""ContactTitle"" = @p1

EF. Functions.Like()EF.Functions.Like()

Dodaliśmy EF. Właściwość funkcji używany przez podstawowych funkcji EF lub dostawców w celu zdefiniowania metody, które mapują funkcje bazy danych i operatorom tak, aby te mogą być wywoływane w zapytaniach składnika LINQ.We have added the EF.Functions property which can be used by EF Core or providers to define methods that map to database functions or operators so that those can be invoked in LINQ queries. Pierwszym przykładzie taka metoda jest Like():The first example of such a method is Like():

var aCustomers =
    from c in context.Customers
    where EF.Functions.Like(c.Name, "a%");
    select c;

Należy pamiętać, że Like() pochodzi z implementacją w pamięci, które mogą być przydatne podczas pracy w bazie danych w pamięci lub oceny predykatu musi nastąpić con po stronie klienta.Note that Like() comes with an in-memory implementation, which can be handy when working against an in-memory database or when evaluation of the predicate needs to occur con the client side.

Zarządzanie bazą danychDatabase management

Hak określania liczby mnogiej dla szkieletów DbContextPluralization hook for DbContext Scaffolding

Podstawowe EF 2.0 wprowadzono nowy IPluralizer , który służy do nadaj jednostki wpisz nazwy i DbSet nazwy w liczbie mnogiej.EF Core 2.0 introduces a new IPluralizer service that is used to singularize entity type names and pluralize DbSet names. Domyślna implementacja jest zerowa, więc jest po prostu haku, gdzie pracowników, można łatwo podłączyć własnych pluralizer.The default implementation is a no-op, so this is just a hook where folks can easily plug in their own pluralizer.

Oto, co wygląda dla deweloperów na utworzenie punktu zaczepienia w ich własnych 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;
    }
}

Inne osobyOthers

Przenieś dostawcy ADO.NET SQLite SQLitePCL.rawMove ADO.NET SQLite provider to SQLitePCL.raw

Zapewnia nam bardziej niezawodne rozwiązanie Microsoft.Data.Sqlite dystrybucji natywne SQLite pliki binarne na różnych platformach.This gives us a more robust solution in Microsoft.Data.Sqlite for distributing native SQLite binaries on different platforms.

Tylko jednego dostawcę dla modeluOnly one provider per model

Znacznie rozszerza dostawców można interakcję z modelu i upraszcza, jak działają adnotacje, fluent API i konwencje z różnych dostawców.Significantly augments how providers can interact with the model and simplifies how conventions, annotations and fluent APIs work with different providers.

Podstawowe EF 2.0 teraz kompilacji w innej IModel dla każdego używanego innego dostawcy.EF Core 2.0 will now build a different IModel for each different provider being used. Jest to zazwyczaj niewidoczne dla aplikacji.This is usually transparent to the application. Ma to ułatwić uproszczenia metadanych niższego poziomu interfejsów API tak, aby wszelkie dostęp do wspólne pojęcia relacyjne metadanych jest zawsze wykonywane za pośrednictwem wywołania .Relational zamiast .SqlServer, .Sqliteitp.This has facilitated a simplification of lower-level metadata APIs such that any access to common relational metadata concepts is always made through a call to .Relational instead of .SqlServer, .Sqlite, etc.

Skonsolidowane rejestrowania i diagnostykiConsolidated Logging and Diagnostics

Rejestrowanie (oparte na ILogger) i mechanizmów diagnostyki (oparte na DiagnosticSource) teraz udostępniać więcej kodu.Logging (based on ILogger) and Diagnostics (based on DiagnosticSource) mechanisms now share more code.

Identyfikatory zdarzeń komunikatów wysyłanych do ILogger zostały zmienione w 2.0.The event IDs for messages sent to an ILogger have changed in 2.0. Identyfikatory zdarzeń obecnie są unikatowe w EF rdzeń kodu.The event IDs are now unique across EF Core code. Te komunikaty teraz również wykonać standardowego wzorca strukturalnych rejestrowania używany przez, na przykład MVC.These messages now also follow the standard pattern for structured logging used by, for example, MVC.

Kategorie rejestratora również zostały zmienione.Logger categories have also changed. Ma teraz dobrze znanego zestawu kategorii dostępne za pośrednictwem DbLoggerCategory.There is now a well-known set of categories accessed through DbLoggerCategory.

Zdarzenia DiagnosticSource teraz użyć tej samej nazwy Identyfikatora zdarzenia odpowiadającego ILogger wiadomości.DiagnosticSource events now use the same event ID names as the corresponding ILogger messages.