Skip to content

EFC 5.0-rc1: Behaviour of IMutableProperty.GetColumnName changed compared to EFC 3.1.8 #22636

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
tivtag opened this issue Sep 21, 2020 · 2 comments

Comments

@tivtag
Copy link

tivtag commented Sep 21, 2020

In EFC 3.1.8 I renamed the columns of owned entities with a single "Value" property to not include the "Value" string in the generated column name. In my application domain I have various owned entities with just a single property.

For example the database column "WorksAt_Value" would be turned into "WorksAt".

For this I created the ConfigureOwnedValueProperties method, see below, which uses IMutableProperty.GetColumnName and IMutableProperty.SetColumnName.

In EFC 3.1.8 this works fine, but in EFC 5.0-rc1 and 6.0.0-alpha.1.20468.4 the methode GetColumnName doesn't return the full column name "WorksAt_Value" anymore, but just "Value".

Debug output of the following program in EFC 3.1.8:

EfcBug.OrganisationKey: Id
EfcBug.OrganisationKey: WorksAt_Value

Debug output of the following program in EFC 5.0-rc1:

EfcBug.OrganisationKey: PersonId
EfcBug.OrganisationKey: Value

Id changed to PersonId.
WorksAt_Value changed to Value.

Is this expected bevhaviour? Should we as customers not use these methods?
But then I couldn't find anything about an expected breaking change in that area?

Thanks :-)

Steps to reproduce:

namespace EfcBug
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Metadata;

    [Table( "Person" )]
    public class Person
    {
        [Key]
        [DatabaseGenerated( DatabaseGeneratedOption.Identity )]
        public int Id { get; set; }
        public string Name { get; set; }

        public OrganisationKey WorksAt { get; set; }
    }

    [Owned]
    public sealed class OrganisationKey
    {
        [Required]
        public uint Value { get; set; }
    }

    public class EfBugDbContext : DbContext
    {
        protected override void OnConfiguring( DbContextOptionsBuilder options )
        {
            options
                .UseSqlServer(
                    "Data Source=localhost;Initial Catalog=TestDB_EfBug_ColumnName;Persist Security Info=True;User ID=User;Password=Pass",
                    providerOptions => providerOptions.EnableRetryOnFailure() )
                .EnableDetailedErrors()
                .EnableSensitiveDataLogging();
        }

        protected override void OnModelCreating( ModelBuilder modelBuilder )
        {
            modelBuilder.Entity<Person>();

            ConfigureOwnedValueProperties( modelBuilder );
        }

        private static void ConfigureOwnedValueProperties( ModelBuilder modelBuilder )
        {
            foreach( IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes() )
            {
                IEnumerable<IMutableProperty> properties = entityType.GetProperties();

                foreach( IMutableProperty prop in properties )
                {
                    Type clrType = prop.DeclaringType.ClrType;
                    if( clrType == typeof( OrganisationKey ) )
                    {
                        string currentColumnName = prop.GetColumnName();
                        Console.WriteLine( clrType + ": " + currentColumnName );

                        if( currentColumnName.EndsWith( "_Value", StringComparison.Ordinal ) )
                        {
                            string alternativeColumnName = currentColumnName.Replace( "_Value", string.Empty );
                            prop.SetColumnName( alternativeColumnName );
                        }
                    }
                }
            }
        }
    }

    public class Program
    {
        static void Main( string[] _ )
        {
            try
            {
                using( EfBugDbContext db = new EfBugDbContext() )
                {
                    db.Database.EnsureDeleted();
                    db.Database.EnsureCreated();
                }

                using( EfBugDbContext db = new EfBugDbContext() )
                {
                    var person = new Person() { Name = "2a", WorksAt = new OrganisationKey() { Value = 1000 } };
                    db.Add( person );
                    db.SaveChanges();
                }

                Console.WriteLine( "OK, please check generated database schema" );
            }
            catch( Exception ex )
            {
                Console.WriteLine( ex.ToString() );
            }

            Console.ReadLine();
        }
    }
}
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <Configurations>Debug;Release;TestRelease;ReleaseKundeProd;ReleaseKundeTest</Configurations>
  </PropertyGroup>
  
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <RootNamespace>EfcBug</RootNamespace>
    <AssemblyName>EfcBug</AssemblyName>
  </PropertyGroup>

  <PropertyGroup>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <LangVersion>latest</LangVersion>
    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
    <Prefer32Bit>false</Prefer32Bit>
    <StartupObject>EfcBug.Program</StartupObject>
  </PropertyGroup>

  <!--<ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0-alpha.1.20468.4" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0-alpha.1.20468.4">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="6.0.0-alpha.1.20468.4" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0-alpha.1.20468.4" />
  </ItemGroup>-->

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.8" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.8">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="3.1.8" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.8" />
  </ItemGroup>

</Project>

Further technical details

EF Core version: 5.0.0-rc.1.20451.13 (doesn't work), 6.0.0-alpha.1.20468.4 (doesn't work), 3.1.8 (works fine!)
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET Core 3.1.8
Operating system: Windows 10 2004
SQL Server 15.0.4063.15
IDE: Visual Studio 2019 16.7.3

@tivtag
Copy link
Author

tivtag commented Sep 21, 2020

#22608 might be related to this?

@ajcvickers
Copy link
Contributor

Duplicate of #22608

@ajcvickers ajcvickers marked this as a duplicate of #22608 Sep 21, 2020
@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

2 participants