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: Allow many properties mapped to one column #3061

Closed
AndriySvyryd opened this issue Sep 8, 2015 · 1 comment
Closed

Migrations: Allow many properties mapped to one column #3061

AndriySvyryd opened this issue Sep 8, 2015 · 1 comment
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Milestone

Comments

@AndriySvyryd
Copy link
Member

This is to unblock the scenario where two derived types have properties with the same name that could be mapped to the same property in TPH.
For the first iteration we could just use the column generated from either property.
As a minimal safeguard we could throw if the generated columns are different in any way, without trying to merge the configurations.

@danielcweber
Copy link

I'm currently running into a similar problem, where I have tow derived types, both with a navigation named "Reference" to a referenced type. Database creation for SQL-Server fails (cannot have two equally named columns). I would not expect this to work out-of-the-box, but every workaround I tried also fails. Here's the entities:

public class BaseType
{
    public string Id { get; set; }
}

public class InheritedType1 : BaseType
{
    public ReferencedType Reference { get; set; }
}

public class InheritedType2 : BaseType
{
    public ReferencedType Reference { get; set; }
}

public class ReferencedType
{
    public string Id { get; set; }
}

And here is the context:

public class TphContext : DbContext
{
    public TphContext(DbContextOptions options): base(options)
    {

    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<ReferencedType>(builder =>
        {
            builder.Key(t => t.Id);
        });

        modelBuilder.Entity<BaseType>(builder =>
        {
            builder.Key(t => t.Id);
        });

        modelBuilder.Entity<InheritedType1>(builder =>
        {
            builder.BaseType<BaseType>();

            builder
                .Reference(t => t.Reference)
                .InverseCollection()
                .Required();
        });

        modelBuilder.Entity<InheritedType2>(builder =>
        {
            builder.BaseType<BaseType>();

            builder
                .Reference(t => t.Reference)
                .InverseCollection()
                .Required();
        });
    }

    public virtual DbSet<BaseType> BaseTypes { get; set; }
    public virtual DbSet<InheritedType1> InheritedTypes1 { get; set; }
    public virtual DbSet<InheritedType2> InheritedTypes2 { get; set; }
    public virtual DbSet<ReferencedType> ReferencedTypes { get; set; }
}

Here is the workaround that should work:

modelBuilder.Entity<InheritedType1>(builder =>
{
    builder.BaseType<BaseType>();

    builder
        .Property<string>("ReferenceId1")
        .MaxLength(450)
        .Required();

    builder
        .Reference(t => t.Reference)
        .InverseCollection()
        .ForeignKey("ReferenceId1")
        .Required();
});

modelBuilder.Entity<InheritedType2>(builder =>
{
    builder.BaseType<BaseType>();

    builder
        .Property<string>("ReferenceId2")
        .MaxLength(450)
        .Required();

    builder
        .Reference(t => t.Reference)
        .InverseCollection()
        .ForeignKey("ReferenceId2")
        .Required();
});

Setting MaxLength to 450 is due to the fact that, at least on SQL Server, string-Keys are of type varchar(450).

This fails: Column 'ReferencedType.Id' is not the same data type as referencing column 'BaseType.ReferenceId1' in foreign key 'FK_InheritedType1_ReferencedType_ReferenceId1'. Once you set the column types explicitly, it works:

builder
    .Property<string>("ReferenceId1")
    .Required()
    .HasSqlServerColumnType("nvarchar(450)");

builder
    .Property<string>("ReferenceId2")
    .Required()
    .HasSqlServerColumnType("nvarchar(450)");

This is odd since everything ends up being nvarchar anyway, the keys end up nvarchar(450) so setting MaxLength to 450 should be equivalent to HasSqlServerColumnType("nvarchar(450)").

The issue I'm running into is probably only #2789 in a different form, however, maybe it adds some insight into this issue as well.

BTW. Does anybody know how to workaround this without setting the column types explicitly? Because I do not want to include anything about the eventual storage in my contexts.

UPDATE: It seems that MaxLength is not reflected on SQL-Server, string-properties are created as nvarchar(max) column. I'm still investigating this since according to #2703 this should have been fixed.

@bricelam bricelam changed the title Allow mapping two properties to the same column Migrations: Allow many properties mapped to one column Sep 25, 2015
@rowanmiller rowanmiller modified the milestones: 7.0.0-rc2, 7.0.0 Dec 9, 2015
@bricelam bricelam modified the milestones: 7.0.0-rc2, 7.0.0 Dec 14, 2015
@ajcvickers ajcvickers modified the milestones: 1.0.0-rc2, 1.0.0 Oct 15, 2022
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Oct 15, 2022
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. type-bug
Projects
None yet
Development

No branches or pull requests

5 participants