Skip to content
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

Migrations: multiple references to the same owned type carries into subsequent migrations #12107

Closed
vslee opened this issue May 22, 2018 · 9 comments
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Milestone

Comments

@vslee
Copy link

vslee commented May 22, 2018

Consider a model with where multiple entities contain the same owned type. There are three entities: two of the same type, and one of a different type. If they call contain the same owned type, then subsequent migrations try to drop the owned type. Please see the code example below. No model changes are made between the migrations for clarity.

PM> Add-Migration MyFirstMigration
To undo this action, use Remove-Migration.
PM> Add-Migration MySecondMigration
An operation was scaffolded that may result in the loss of data. Please review the migration for accuracy.
To undo this action, use Remove-Migration.

Steps to reproduce

Commenting out either line below (and the corresponding lines in OnModelCreating) fixes the problem.

using Microsoft.EntityFrameworkCore;

namespace OwnedTypeMigrationTest
{
	class Program
	{
		static void Main(string[] args) { }
	}

	public class MyContext : DbContext
	{
		public DbSet<Order> Orders { get; set; }
		protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
		{
			optionsBuilder.UseSqlServer(@"Data Source=" + System.Environment.MachineName +
				";Initial Catalog=ownedTypeMigrationTest;" + "Integrated Security=True" +
				";Connect Timeout=15;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
			optionsBuilder.EnableSensitiveDataLogging();
			optionsBuilder.ConfigureWarnings(w => w.Log(
				Microsoft.EntityFrameworkCore.Diagnostics.CoreEventId.SensitiveDataLoggingEnabledWarning));
		}
		protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
			modelBuilder.Entity<Order>().OwnsOne(p => p.OrderBillingDetails, od =>
			{
				od.OwnsOne(c => c.StreetAddress);
			});
			modelBuilder.Entity<Order>().OwnsOne(p => p.OrderShippingDetails, od =>
			{
				od.OwnsOne(c => c.StreetAddress);
			});
			modelBuilder.Entity<Order>().OwnsOne(p => p.OrderInfo, od =>
			{
				od.OwnsOne(c => c.StreetAddress);
			});
		}
	}

	public class Order
	{
		public int Id { get; set; }
		public OrderDetails OrderBillingDetails { get; set; }
		public OrderDetails OrderShippingDetails { get; set; } // commenting out this line (and in OnModelCreating) fixes the problem
		public OrderInfo OrderInfo { get; set; } // commenting out this line and leaving the one above also fixes the problem
	}

	public class OrderDetails
	{
		public StreetAddress StreetAddress { get; set; }
	}

	public class OrderInfo
	{
		public StreetAddress StreetAddress { get; set; }
	}

	public class StreetAddress
	{
		public string City { get; set; }
	}
}

Here are the contents of the migration files:
20180522184202_MyFirstMigration.cs

using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

namespace UniqueIndexTest.Migrations
{
    public partial class MyFirstMigration : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Orders",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                    OrderBillingDetails_StreetAddress_City = table.Column<string>(nullable: true),
                    OrderShippingDetails_StreetAddress_City = table.Column<string>(nullable: true),
                    OrderInfo_StreetAddress_City = table.Column<string>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Orders", x => x.Id);
                });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Orders");
        }
    }
}

20180522184211_MySecondMigration.cs

using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

namespace UniqueIndexTest.Migrations
{
    public partial class MySecondMigration : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropColumn(
                name: "OrderBillingDetails_StreetAddress_OrderDetailsOrderId",
                table: "Orders");
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AddColumn<int>(
                name: "OrderBillingDetails_StreetAddress_OrderDetailsOrderId",
                table: "Orders",
                nullable: false,
                defaultValue: 0)
                .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
        }
    }
}

Further technical details

EF Core version: v2.1.0-rc1-final
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10 Pro 17134.48
IDE: Visual Studio 2017 15.7.1

@vslee vslee changed the title Migrations: multiple references to the same owned type carries into subsequent migration Migrations: multiple references to the same owned type carries into subsequent migrations May 22, 2018
@ajcvickers ajcvickers added this to the 2.1.1 milestone May 25, 2018
@ajcvickers
Copy link
Contributor

@bricelam Any update on the investigation here? Specifically, is it something we might want to patch?

@bricelam
Copy link
Contributor

bricelam commented May 29, 2018

Something strange is going on when building the model in the snapshot. The Entity<Order>().OwnsOne(p => p.OrderBillingDetails).OwnsOne(c => c.StreetAddress) entity type ends up having two OrderDetailsOrderId properties. I think I need @AndriySvyryd to continue the investigation.

@bricelam
Copy link
Contributor

bricelam commented May 29, 2018

Removing these lines from the snapshot fixes the issue for one migration. (They're re-scaffolded into the next snapshot).

b2.Property<int>("OrderDetailsOrderId")
    .ValueGeneratedOnAdd()
    .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

b2.HasOne("OwnedTypeMigrationTest.OrderDetails")
    .WithOne("StreetAddress")
    .HasForeignKey("OwnedTypeMigrationTest.StreetAddress", "OrderDetailsOrderId")
    .OnDelete(DeleteBehavior.Cascade);

@bricelam
Copy link
Contributor

bricelam commented May 29, 2018

Here are the interesting parts of the debug view:

EntityType: OwnedTypeMigrationTest.StreetAddress
  Properties: 
    OwnedTypeMigrationTest.OrderDetailsOrderId (no field, int) Shadow Required PK FK AfterSave:Throw 0 0 0 0 0
    OrderDetailsOrderId (no field, int) Shadow Required ValueGenerated.OnAdd 2 2 -1 2 1
      Annotations: 
        SqlServer:ValueGenerationStrategy: IdentityColumn
  Keys: 
    OwnedTypeMigrationTest.OrderDetailsOrderId PK
  Foreign keys: 
    OwnedTypeMigrationTest.StreetAddress {'OwnedTypeMigrationTest.OrderDetailsOrderId'} -> OwnedTypeMigrationTest.OrderDetails {'OrderId'} Unique Ownership ToDependent: StreetAddress

@bricelam bricelam reopened this May 29, 2018
@ajcvickers
Copy link
Contributor

@AndriySvyryd Did you get a chance to look at this with regard to whether we should try to patch? June patch deadline is tomorrow.

@AndriySvyryd
Copy link
Member

@ajcvickers I'm still investigating

@bricelam bricelam removed their assignment May 31, 2018
@ajcvickers
Copy link
Contributor

Moving this to 2.1.3, since 2.1.1 is now in escrow.

@ajcvickers ajcvickers modified the milestones: 2.1.1, 2.1.3 Jun 4, 2018
AndriySvyryd added a commit that referenced this issue Jun 7, 2018
…pshot.

Fix ShortName() for shadow entity types.
Make the shadow property for identifying FKs be of a non-nullable type in more cases.

Port of #12107 fix
AndriySvyryd added a commit that referenced this issue Jun 7, 2018
AndriySvyryd added a commit that referenced this issue Jun 8, 2018
…pshot.

Fix ShortName() for shadow entity types.
Make the shadow property for identifying FKs be of a non-nullable type in more cases.

Port of #12107 fix
@AndriySvyryd AndriySvyryd added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Jun 12, 2018
@ajcvickers
Copy link
Contributor

This is approved for 2.1.3. Do not merge yet; branch is expected to open Monday.

Given these issues have been parked for some time, please be careful to ensure the correct commits get into the correct branches.

@ajcvickers
Copy link
Contributor

ajcvickers commented Jun 27, 2018

@AndriySvyryd This issue is approved for patch and the release\2.1 branch is now open for merging. Please ensure:

  • The appropriate changes get into both the release and dev branches
  • Quirking is included for the release branch only

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Projects
None yet
Development

No branches or pull requests

4 participants