Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Table splitting EF Core

Tags:

I'm trying to use table spliting in EF core. I have an int property that I want to share between two entities stored in the same table.

I get an InvalidOperationException saying that the properties sharing the same column have different nullability.

I have recreated the problem using the Table splitting sample from EF Core Docs.

https://docs.microsoft.com/en-us/ef/core/modeling/table-splitting https://github.com/aspnet/EntityFramework.Docs/tree/master/samples/core/Modeling/TableSplitting

public class Order
{
    public int Id { get; set; }
    public OrderStatus? Status { get; set; }
    public int SharedInt { get; set; }
    public DetailedOrder DetailedOrder { get; set; }
}

public class DetailedOrder
{
    public int Id { get; set; }
    public OrderStatus? Status { get; set; }
    public string BillingAddress { get; set; }
    public string ShippingAddress { get; set; }
    public int SharedInt { get; set; }
    public byte[] Version { get; set; }
}

 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            #region TableSplitting
            modelBuilder.Entity<DetailedOrder>(dob =>
            {
                dob.ToTable("Orders");
                dob.Property(o => o.Status).HasColumnName("Status");
                dob.Property(p => p.SharedInt).HasColumnName("Shared");
            });

            modelBuilder.Entity<Order>(ob =>
            {
                ob.ToTable("Orders");
                ob.Property(o => o.Status).HasColumnName("Status");
                ob.Property(p => p.SharedInt).HasColumnName("Shared");

                ob.HasOne(o => o.DetailedOrder).WithOne()
                    .HasForeignKey<DetailedOrder>(o => o.Id);
            });

            #endregion

            #region ConcurrencyToken
            modelBuilder.Entity<Order>()
                .Property<byte[]>("Version").IsRowVersion().HasColumnName("Version");

            modelBuilder.Entity<DetailedOrder>()
                .Property(o => o.Version).IsRowVersion().HasColumnName("Version");
            #endregion
        }

When I run the sample I get an exception:

System.InvalidOperationException: ''DetailedOrder.SharedInt' and 'Order.SharedInt' are both mapped to column 'Shared' in 'Orders' but are configured with different nullability.'

If I don't map the properties to specific columns, leaving it to EF Core. I can see (looking in the created migration) that one of the properties is nullable == true despite it beeing an non-nullable int.

 protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Orders",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
                    Status = table.Column<int>(nullable: true),
                    Order_SharedInt = table.Column<int>(nullable: false),
                    BillingAddress = table.Column<string>(nullable: true),
                    ShippingAddress = table.Column<string>(nullable: true),
                    SharedInt = table.Column<int>(nullable: true),
                    Version = table.Column<byte[]>(rowVersion: true, nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Orders", x => x.Id);
                });
        }

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

Any thoughts?

like image 887
Andreas Stenbäck Avatar asked Jan 30 '20 08:01

Andreas Stenbäck


1 Answers

Unfortunately currently (EF Core 3.1) there is no solution.

This is a side effect of the following EF Core 3.0 breaking change - Dependent entities sharing the table with the principal are now optional.

Interestingly, they consider it having Low impact, but the way it is implemented (by making all dependent non key properties nullable) is breaking many things, including their own table splitting example.

Looks like the issue is tracked as enhancement request (?!) by #12100: Enable configuring required 1-to-1 dependents with unknown timeframe for addressing (eventually consider for "next" release, whatever that means). All reported related issues (for instance #18574: Table splitting isn't working with nonnullable reference types. which is similar to this one) are closed as "duplicate", although it's really a regression.

like image 56
Ivan Stoev Avatar answered Nov 10 '22 04:11

Ivan Stoev