I get the the following error message when I try to update the database after generating a migration. It works fine on 2.1. The issue appeared when I updated my TargetFramework to netcoreapp2.2.
The property 'AccountId' on entity type 'MigrationBugRepro.Models.Account.MainAddress#MigrationBugRepro.Models.Address' cannot be marked as nullable/optional because it has been included in a key {'AccountId'}.
Given this DatabaseContext:
```c#
public class ApplicationContext : DbContext
{
public ApplicationContext(DbContextOptions
{
}
public virtual DbSet<Account> Accounts { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Account>(b =>
{
b.HasKey(x => x.AccountId);
b.Property(e => e.AccountId).HasMaxLength(36).IsRequired();
// Multiple Owned Types
// Works if I only have one Owned address object, issue appears with 2 or more objects of the same type
b.OwnsOne(e => e.MainAddress, a =>
{
a.Property(x => x.AddressLine1).HasMaxLength(256);
a.Property(x => x.City).HasMaxLength(256);
});
b.OwnsOne(e => e.SecondaryAddress, a =>
{
a.Property(x => x.AddressLine1).HasMaxLength(256);
a.Property(x => x.City).HasMaxLength(256);
});
});
}
}
And those models:
```c#
public class Account
{
public string AccountId { get; set; }
public Address MainAddress { get; set; }
public Address SecondaryAddress { get; set; }
}
public class Address
{
public string AddressLine1 { get; set; }
public string City { get; set; }
}
You can find a sample Project here
EF Core version: 2.2.0-preview3-35497
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10
IDE: Visual Studio 2017 15.9.2
Note for triage: I am able to reproduce this on 2.2 preview3, but only when doing update-database after creating a migration. Conversly, EnsureCreated on the same code does not throw. Also does not throw if PK is changed from string to int.
Generated migration:
```C#
public partial class One : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Accounts",
columns: table => new
{
AccountId = table.Column
MainAddress_AddressLine1 = table.Column
MainAddress_City = table.Column
SecondaryAddress_AddressLine1 = table.Column
SecondaryAddress_City = table.Column
},
constraints: table =>
{
table.PrimaryKey("PK_Accounts", x => x.AccountId);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Accounts");
}
}
Full stack trace:
PM> update-database
Applying migration '20181126214128_One'.
System.InvalidOperationException: The property 'AccountId' on entity type 'Account.MainAddress#Address' cannot be marked as nullable/optional because it has been included in a key {'AccountId'}.
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalPropertyBuilder.IsRequired(Boolean isRequired, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.IsRequired(Boolean isRequired, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.ReplaceForeignKey(InternalEntityTypeBuilder principalEntityTypeBuilder, InternalEntityTypeBuilder dependentEntityTypeBuilder, Nullable1 navigationToPrincipal, Nullable1 navigationToDependent, IReadOnlyList1 dependentProperties, IReadOnlyList1 principalProperties, Nullable1 isUnique, Nullable1 isRequired, Nullable1 isOwnership, Nullable1 deleteBehavior, Boolean removeCurrent, Boolean oldRelationshipInverted, Nullable1 principalEndConfigurationSource, Nullable1 configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.ReplaceForeignKey(Nullable1 configurationSource, InternalEntityTypeBuilder principalEntityTypeBuilder, InternalEntityTypeBuilder dependentEntityTypeBuilder, Nullable1 navigationToPrincipal, Nullable1 navigationToDependent, IReadOnlyList1 dependentProperties, IReadOnlyList1 principalProperties, Nullable1 isUnique, Nullable1 isRequired, Nullable1 isOwnership, Nullable1 deleteBehavior, Boolean removeCurrent, Nullable1 principalEndConfigurationSource, Boolean oldRelationshipInverted)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.Attach(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.RelationshipSnapshot.Attach(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.PropertiesSnapshot.Attach(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityType.Snapshot.Attach(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(TypeIdentity& type, String definingNavigationName, EntityType definingEntityType, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(String name, String definingNavigationName, EntityType definingEntityType, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.IsWeakTypeDefinition(ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.Owns(TypeIdentity& targetEntityType, PropertyIdentity navigation, Nullable1 inverse, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.Owns(String targetEntityTypeName, String navigationName, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.OwnsOneBuilder(TypeIdentity& ownedType, String navigationName)
at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.OwnsOne(String ownedTypeName, String navigationName, Action1 buildAction)
at TwoTwoPreview.Migrations.One.<>c.
at Microsoft.EntityFrameworkCore.ModelBuilder.Entity(String name, Action1 buildAction)
at TwoTwoPreview.Migrations.One.BuildTargetModel(ModelBuilder modelBuilder) in C:\Stuff\TwoTwoPreview\TwoTwoPreview\Migrations\20181126214128_One.Designer.cs:line 33
at Microsoft.EntityFrameworkCore.Migrations.Migration.<.ctor>b__4_0()
at Microsoft.EntityFrameworkCore.Internal.LazyRef1.get_Value()
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.GenerateUpSql(Migration migration)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The property 'AccountId' on entity type 'Account.MainAddress#Address' cannot be marked as nullable/optional because it has been included in a key {'AccountId'}.
PM>
```
This is the code inside designer file which throws exception:
Putting below in OnModelCreating throws too. There does not seem to be anything particularly wrong with generated migration designer file. It seems like bug in model building code with shadow types.
```C#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Configure model
modelBuilder.Entity("EFSampleApp.Account", b =>
{
b.Property
.ValueGeneratedOnAdd()
.HasMaxLength(36);
b.HasKey("AccountId");
});
modelBuilder.Entity("EFSampleApp.Account", b =>
{
b.OwnsOne("EFSampleApp.Address", "MainAddress", b1 =>
{
b1.Property<string>("AccountId");
b1.HasKey("AccountId");
b1.HasOne("EFSampleApp.Account")
.WithOne("MainAddress")
.HasForeignKey("EFSampleApp.Address", "AccountId")
.OnDelete(DeleteBehavior.Cascade);
});
b.OwnsOne("EFSampleApp.Address", "SecondaryAddress", b1 =>
{
b1.Property<string>("AccountId");
b1.HasKey("AccountId");
b1.HasOne("EFSampleApp.Account")
.WithOne("SecondaryAddress")
.HasForeignKey("EFSampleApp.Address", "AccountId")
.OnDelete(DeleteBehavior.Cascade);
});
});
}
```
We've found a workaround for this issue. There are actually two problems:
For 1., edit ApplicationDbContextModelSnapshot.cs
Revert "ProductVersion" to "2.1.4-rtm-31024":
modelBuilder
.HasAnnotation("ProductVersion", "2.1.4-rtm-31024" /* <-- This was "2.2.0-rtm-35687" */)
In each OwnsOne block for the problematic owned property, remove the HasKey(...) line:
b.OwnsOne("EFSampleApp.Address", "MainAddress", b1 =>
{
...
//b1.HasKey("AccountId"); <-- Comment or remove this line
...
});
You must do this for every new migration since this file is re-generated every time.
For 2., edit the generated xxxxxxxxxxxxxx_MyMigration.Designer.cs file
In each OwnsOne block for the problematic owned property, remove the HasKey(...) line:
b.OwnsOne("EFSampleApp.Address", "MainAddress", b1 =>
{
...
//b1.HasKey("AccountId"); <-- Comment or remove this line
...
});
It's not necessary to change the "ProductVersion" in this file.
It didn't work for me. Is there any other thing that I can do?
@tiagor87 Are you referring to the fix checked in or the workaround in the previous comment?
@ajcvickers the workaround
@tiagor87 I just tried to reproduce the issue with servicing version 2.2.1-servicing-35743 of EF Core and it looks like this bug is fixed.
This is the package: https://dotnet.myget.org/feed/aspnetcore-dev/package/nuget/Microsoft.EntityFrameworkCore/2.2.1-servicing-35743
In order to use this version, you need to add the MyGet feed as a package source. You can do this by adding a Nuget.config file at the root of your solution:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="ASPNETCoreDevNightly" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json" />
</packageSources>
</configuration>
Hope this helps.
Most helpful comment
Note for triage: I am able to reproduce this on 2.2 preview3, but only when doing update-database after creating a migration. Conversly, EnsureCreated on the same code does not throw. Also does not throw if PK is changed from string to int.
Generated migration:(maxLength: 36, nullable: false),(maxLength: 256, nullable: true),(maxLength: 256, nullable: true),(maxLength: 256, nullable: true),(maxLength: 256, nullable: true)
```C#
public partial class One : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Accounts",
columns: table => new
{
AccountId = table.Column
MainAddress_AddressLine1 = table.Column
MainAddress_City = table.Column
SecondaryAddress_AddressLine1 = table.Column
SecondaryAddress_City = table.Column
},
constraints: table =>
{
table.PrimaryKey("PK_Accounts", x => x.AccountId);
});
}
}
PM> update-databaseb__2_1(EntityTypeBuilder b) in C:StuffTwoTwoPreviewTwoTwoPreviewMigrations20181126214128_One.Designer.cs:line 55
Applying migration '20181126214128_One'.
System.InvalidOperationException: The property 'AccountId' on entity type 'Account.MainAddress#Address' cannot be marked as nullable/optional because it has been included in a key {'AccountId'}.
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalPropertyBuilder.IsRequired(Boolean isRequired, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.IsRequired(Boolean isRequired, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.ReplaceForeignKey(InternalEntityTypeBuilder principalEntityTypeBuilder, InternalEntityTypeBuilder dependentEntityTypeBuilder, Nullable
1 navigationToPrincipal, Nullable1 navigationToDependent, IReadOnlyList1 dependentProperties, IReadOnlyList1 principalProperties, Nullable1 isUnique, Nullable1 isRequired, Nullable1 isOwnership, Nullable1 deleteBehavior, Boolean removeCurrent, Boolean oldRelationshipInverted, Nullable1 principalEndConfigurationSource, Nullable1 configurationSource)at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.ReplaceForeignKey(Nullable
1 configurationSource, InternalEntityTypeBuilder principalEntityTypeBuilder, InternalEntityTypeBuilder dependentEntityTypeBuilder, Nullable1 navigationToPrincipal, Nullable1 navigationToDependent, IReadOnlyList1 dependentProperties, IReadOnlyList1 principalProperties, Nullable1 isUnique, Nullable1 isRequired, Nullable1 isOwnership, Nullable1 deleteBehavior, Boolean removeCurrent, Nullable1 principalEndConfigurationSource, Boolean oldRelationshipInverted)at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.Attach(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.RelationshipSnapshot.Attach(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.PropertiesSnapshot.Attach(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityType.Snapshot.Attach(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(TypeIdentity& type, String definingNavigationName, EntityType definingEntityType, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(String name, String definingNavigationName, EntityType definingEntityType, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.IsWeakTypeDefinition(ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.Owns(TypeIdentity& targetEntityType, PropertyIdentity navigation, Nullable
1 inverse, ConfigurationSource configurationSource) at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.Owns(String targetEntityTypeName, String navigationName, ConfigurationSource configurationSource) at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.OwnsOneBuilder(TypeIdentity& ownedType, String navigationName) at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.OwnsOne(String ownedTypeName, String navigationName, Action1 buildAction)at TwoTwoPreview.Migrations.One.<>c.
at Microsoft.EntityFrameworkCore.ModelBuilder.Entity(String name, Action
1 buildAction) at TwoTwoPreview.Migrations.One.BuildTargetModel(ModelBuilder modelBuilder) in C:\Stuff\TwoTwoPreview\TwoTwoPreview\Migrations\20181126214128_One.Designer.cs:line 33 at Microsoft.EntityFrameworkCore.Migrations.Migration.<.ctor>b__4_0() at Microsoft.EntityFrameworkCore.Internal.LazyRef1.get_Value()at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.GenerateUpSql(Migration migration)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The property 'AccountId' on entity type 'Account.MainAddress#Address' cannot be marked as nullable/optional because it has been included in a key {'AccountId'}.
PM>
```