-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Write announcements for significant changes introduced in EF Core 2.0 #8923
Comments
Initial drafts for my breaking change sections EF Core 2.0 requires a 2.0 database providerFor EF Core 2.0 we have made many simplifications and improvements in the way database providers work. This means that 1.0.x and 1.1.x providers will not work with EF Core 2.0. The SQL Server and SQLite providers are shipped by the EF team and 2.0 versions will be available as part of the 2.0 release. The open-source third party providers for SQL Compact, PostgreSQL, and MySQL are being updated for 2.0. For all other providers, please contact the provider writer. Logging and Diagnostics events have changedNote: these changes should not impact most application code. The event IDs for messages sent to an ILogger have changed in 2.0. The event IDs are now unique across EF Core code. These messages now also follow the standard pattern for structured logging used by, for example, MVC. Logger categories have also changed. There is now a well-known set of categories accessed through DbLoggerCategory. DiagnosticSource events now use the same event ID names as the corresponding Event IDs, payload types, and categories are documented in the CoreEventId and the RelationalEventId classes. EF Core relational metadata API changesEF Core 2.0 will now build a different IModel for each different provider being used. This is usually transparent to the application. 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 var tableName = context.Model.FindEntityType(typeof(User)).SqlServer().TableName; Should now be written like this: var tableName = context.Model.FindEntityType(typeof(User)).Relational().TableName; Instead of using methods like modelBuilder.Entity<User>().ToTable(
Database.IsSqlServer() ? "SqlServerName" : "OtherName"); Note that this change only applies to APIs/metadata that is defined for all relational providers. The API and metadata remains the same when it is specific to only a single provider. For example, clustered indexes are specific to SQL Sever, so Don’t take control of the EF service providerEF Core uses an internal Calling In-memory databases must be namedThe global unnamed in-memory database has been removed and instead all in-memory databases must be named. For example: optionsBuilder.UseInMemoryDatabase("MyDatabase"); This creates/uses a database with the name “MyDatabase”. If Read-only API changes
Properties marked as ValueGenerated.OnAddOrUpdate (e.g. for computed columns) will by default ignore any value currently set on the property. This means that a store-generated value will always be obtained regardless of whether any value has been set or modified on the tracked entity. This can be changed by setting a different New ClientSetNull delete behaviorIn previous releases, DeleteBehavior.Restrict had a behavior for entities tracked by the context that more closed matched |
You'll want to fix the spelling of AfterSaveBhevaior in the Read-only Api Changes section. |
@DannyMeister Thanks. |
Provider design-time packages removedThe This propagates into the provider design-time packages. Those packages ( To enable
|
Brice, I find it slightly confusing that you have mentioned a non-existing package in the sample csproj file, despite the coloring |
Agreed. I was hoping it would |
EF Core design-time DbContext discovery changesThere have been some changes made in 2.0 to the way EF Core discovers and creates your New way of getting application servicesThe recommended pattern for ASP.NET Core web applications has been updated for 2.0 in a way that broke EF Core's design-time logic. Previously at design-time, EF Core would try to invoke
A new design-time hook has been added in ASP.NET Core 2.0. The static public class Program
{
public static void Main(string[] args)
{
var host = BuildWebHost(args);
host.Run();
}
// Tools will use this to get application services
public static IWebHost BuildWebHost(string[] args) =>
new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
} IDbContextFactory renamedIn order to support diverse application patterns and give users more control over how their This interface had a very general name which mislead some users to try re-using it for other In order to communicate the strong design-time semantics of this interface, we have renamed it to DbContextFactoryOptions removedBecause of the ASP.NET Core 2.0 changes described above, we found that
|
Model-level query filtersEF Core 2.0 includes a new feature we call Model-level query filters. 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). 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. Some common applications of this feature are:
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 );
}
} We define a model-level filter that implements multi-tenancy and soft-delete for instances of the Filters may be disabled for individual LINQ queries using the IgnoreQueryFilters() operator. Limitations
|
DbContext pooling and explicit compiled queriesIn EF Core 2.0 we added two new opt-in performance features designed to offer benefits in high-scale scenarios. DbContext poolingThe 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. This means a new instance of the DbContext is created for each requests. 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. To use DbContext pooling, use the services.AddDbContextPool<BloggingContext>(options => options.UseSqlServer(connectionString)); 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. Once the request processing finalizes, any state on the instance is reset and the instance is itself returned to the pool. 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. The new method introduces a few limitations on what can be done in the Explicit compiled queriesManual 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. 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 explicit 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);
} |
String interpolation in FromSql and ExecuteSqlCommandC# 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. In EF Core 2.0 we added special support for interpolated strings to our two primary APIs that accept raw SQL strings: 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();
} In this example, there are two variables embedded in the SQL format string. 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 |
@pmiddleton If you are interested in writing the announcement post for DbFunctions, you can write it here. Up to you, but I thought I would give you the option 😄 |
I'll take a crack at it. |
How about: EF Core 2.0 no longer works with .NET 4.5.1, but requires 4.6.1 ? |
(Added a comment about .NET Framework 4.6.1 to the .NET Standed 2.0 item.) |
Attach can track a graph of new and existing entitiesEF 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 |
Warning as error for ignored IncludesA very common issue we see when looking at user LINQ queries is the use of context.Orders.Include(o => o.Product).Where(o => o.Product.Name == "Baked Beans").Select(o =>o.ProductId).ToList(); One might assume that the Previously we would generate a warning when we encountered queries like this, but in EF Core 2.0 we are changing the default That said, it is easy to configure EF Core to use the previous, non-throwing behavior via our flexible 'warnings-as-errors' configuration system. // In OnConfiguring or AddDbContext during start-up
optionsBuilder.ConfigureWarnings(w => w.Log(CoreEventId.IncludeIgnoredWarning)); // Log but don't throw |
@AndriySvyryd Can you work on your sections today--then we can hand off to @divega. |
I didn't have time this weekend to work my section. I will tonight, but if there is a close deadline someone else can take it. |
@AndriySvyryd Thanks. Glad to hear. It would be great if you can either give me a fixed example or more information about the workaround (I tried what I understood by "rename the navigation to change the order", but didn't help). I would like to update the preview2 announcement blog post with code that works, or otherwise add a disclaimer that this won't work correctly until RTM. |
@divega Renaming |
@AndriySvyryd I tried out the Owner Types in Preview2 with the following classes: public class ParentClass {
[Required]
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public virtual OwnedClass Ref { get; set; }
}
public class OwnedClass
{
public string Field1 { get; set; }
public string Field2 { get; set; }
} and the following Mapping: modelBuilder.Entity<ParentClass>()
.OwnsOne<OwnedClass>(s => s.Ref, cb =>
{
cb.Property(c => c.Field1).HasColumnName("OwnedField1");
cb.Property(c => c.Field2).HasColumnName("OwnedField2");
}); Although it is stated above that when querying the owner (ParentClass) the owned types will be included by default, in my tests I have to explicitly include the "Ref" property. In this case loading works, however I ran into a few problems:
Are these issues known in Preview 2? |
@AndriySvyryd Thanks, that was quick! Another question regarding owned types: is it possible to define a custom index over the columns in the owned type? Something like this: modelBuilder.Entity<ParentClass>()
.OwnsOne<OwnedClass>(s => s.Ref, cb =>
{
cb.Property(c => c.Field1).HasColumnName("OwnedField1");
cb.Property(c => c.Field2).HasColumnName("OwnedField2");
});
modelBuilder.Entity<ParentClass>()
.HasIndex(s => new { s.Ref.Field1, s.Ref.Field2 }).HasName("IDX_CustomName"); |
@arjenvrh There's an issue in preview2 with the generic overload #9106. But you can just create the index in the owned type configuration: modelBuilder.Entity<ParentClass>()
.OwnsOne<OwnedClass>(s => s.Ref, cb =>
{
cb.Property(c => c.Field1).HasColumnName("OwnedField1");
cb.Property(c => c.Field2).HasColumnName("OwnedField2");
cb.HasIndex("Field1", "Field2").HasName("IDX_CustomName");
}); However we don't support creating indexes that span across types, but if that's important for your scenario file it as a separate issue. |
This was all added to the documentation page at https://docs.microsoft.com/en-us/ef/core/what-is-new/index on time for 2.0. Only created announcements for the specially controversial decisions in which we needed to actively seek for feedback the most. |
- AutoMapper 6.2.2 - Microsoft.EntityFrameworkCore.SqlServer.Design 1.1.5 - System.ComponentModel.Annotations 4.4.1
This is an initial list of areas where an announcement might be useful. We will edit and update this list based on discussions within the team. We would also welcome feedback from anyone else who has used pre-release versions and has discovered something that would have been good for us to announce.
Discussed in triage and we will do one general announcement for impactful breaking changes and one general announcement for significant new features. Some very significant changes will have their own announcements.
Initial idea for process is:
Throw for ignored includes (include that it can be configured to not throw) @anpeteEF Core 2.0: Warning as error for ignored calls to Include() aspnet/Announcements#256Design-time DbContext discovery changes (BuildWebHost, IDbContextFactory, etc.) @bricelamEF Core 2.0: design-time DbContext discovery changes aspnet/Announcements#258.NET Standard 2.0/No UPW yet/4.6.1 @divegaEF Core 2.0 to target .NET Standard 2.0 aspnet/Announcements#246 and Microsoft.Data.Sqlite 2.0 to target .NET Standard 2.0 aspnet/Announcements#247The text was updated successfully, but these errors were encountered: