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

Backing fields that participate in seeding not work properly, when we use them for transforming (change/reformat) the data that coming from or going to the database #25459

Closed
ghost opened this issue Aug 9, 2021 · 0 comments · Fixed by #25960
Labels
area-migrations-seeding 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

@ghost
Copy link

ghost commented Aug 9, 2021

Hello,
I have a simple sample code that shows a problem with backing fields when we use them in seeding, while we use them also to transform (change/reformat) data coming from or going to the database.

This is our AppDbContext class.

public class AppDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer($@"server=.\mssqlserver20191;database={nameof(EfCoreBackingFieldSeeding)};user id=sa;password=2019");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //first row - insert 
        modelBuilder.Entity<Person>().HasData(new Person { Id = 1, Name = "Kurosh", Gender = Gender.Male });
    }

    public DbSet<Person> People { get; set; }
}

And this is my Entity class.

public class Person
{
    public int Id { get; set; }
    private string _name;
    public string Name
    {
        get
        {
            return Gender switch
            {
                Male => "Mr. ",
                Female => "Miss. ",
                Other => "Dear, ",
                _ => string.Empty
            } + _name;
        }
        set => _name = value;
    }
    public Gender Gender { get; set; }

    //override
    public override string ToString() =>
        $"[Id]: {Id:00} - [Name]: {Name,-15} - [Gender]: {Enum.GetName(Gender)}";
}

We have the Gender enum type that transforms our entity Name base on the gender of the person (as you can see in the get accessor of the Name property in the above code).

public enum Gender
{
    Male,
    Female,
    Other
}

As you can see in our AppDbContext we seed our database with an instance of our Entity like this:

 //first row - insert 
 modelBuilder.Entity<Person>().HasData(new Person { Id = 1, Name = "Kurosh", Gender = Gender.Male });

After this, we add our initial migration (dotnet ef migrations add Initial). And then update our database (dotnet ef database update)

What we expected is that we have 1 row of data like this in our database(People table):

Id Name Gender
1 Kurosh 0

But real data in our database is this row:

Id Name Gender
1 Mr. Kurosh 0

•••••••

According to this code in our entity class:

private string _name;
public string Name
{
    get
    {
        return Gender switch
        {
            Male => "Mr. ",
            Female => "Miss. ",
            Other => "Dear, ",
            _ => string.Empty
        } + _name;
    }
    set => _name = value;
}

EF core didn't see _name backing field and get back his data from get accessor of Name property (add Mr. to the name of the person based on the gender)!
Where is the backing field in this scenario?

This is while when we add a new person to our database in our Program.Main method we don't have this problem (EF core see and use our _name backing field, instead of the Name property)

This is our Program class code:

class Program
{
    static AppDbContext context = new();

    static void Main(string[] args)
    {

        WriteAllPeopleInfo();
        AddThisPersonIfNotExist();
        WriteAllPeopleInfo();

        ReadLine();
    }

    static void WriteAllPeopleInfo()
    {
        List<Person> people = context.People.ToList();
        foreach (Person person in people)
            WriteLine(person);
        SeparateLine();
    }

    //second row - insert
    static void AddThisPersonIfNotExist()
    {
        if (context.People.Count() >= 2) return;

        context.Add(new Person { Name = "Dariush", Gender = Male });
        context.SaveChanges();
    }

    static void SeparateLine() => WriteLine(new string('-', 60));
}

When we run our code output is:

[Id]: 01 - [Name]: Mr. Mr. Kurosh  - [Gender]: Male
------------------------------------------------------------
[Id]: 01 - [Name]: Mr. Mr. Kurosh  - [Gender]: Male
[Id]: 02 - [Name]: Mr. Dariush     - [Gender]: Male
------------------------------------------------------------
@ghost ghost added the customer-reported label Aug 9, 2021
@ghost ghost changed the title Backing filed seeding not work properly, when we use the backing field for transform (change/reformat) data coming from or going to the database Backing fields that participate in seeding not work properly, when we use the them for transforming (change/reformat) data that coming from or going to the database Aug 9, 2021
@ghost ghost changed the title Backing fields that participate in seeding not work properly, when we use the them for transforming (change/reformat) data that coming from or going to the database Backing fields that participate in seeding not work properly, when we use them for transforming (change/reformat) data that coming from or going to the database Aug 9, 2021
@ghost ghost changed the title Backing fields that participate in seeding not work properly, when we use them for transforming (change/reformat) data that coming from or going to the database Backing fields that participate in seeding not work properly, when we use them for transforming (change/reformat) the data that coming from or going to the database Aug 9, 2021
@ajcvickers ajcvickers added this to the 6.0.0 milestone Aug 10, 2021
@AndriySvyryd AndriySvyryd removed their assignment Sep 10, 2021
@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 Sep 10, 2021
AndriySvyryd added a commit that referenced this issue Sep 10, 2021
…erties.

Make GetIdentifyingMemberInfo() return null for indexer properties since it doesn't uniquely identifies them
Replaced some usages of GetIdentifyingMemberInfo() with more appropriate code.

Fixes #25501
Fixes #25459
AndriySvyryd added a commit that referenced this issue Sep 10, 2021
…erties.

Make GetIdentifyingMemberInfo() return null for indexer properties since it doesn't uniquely identifies them
Replaced some usages of GetIdentifyingMemberInfo() with more appropriate code.

Fixes #25501
Fixes #25459
AndriySvyryd added a commit that referenced this issue Sep 10, 2021
…erties.

Make GetIdentifyingMemberInfo() return null for indexer properties since it doesn't uniquely identify them
Replaced some usages of GetIdentifyingMemberInfo() with more appropriate code.

Fixes #25501
Fixes #25459
@ajcvickers ajcvickers modified the milestones: 6.0.0, 6.0.0-rc2 Sep 10, 2021
@ajcvickers ajcvickers modified the milestones: 6.0.0-rc2, 6.0.0 Nov 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-migrations-seeding 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

Successfully merging a pull request may close this issue.

2 participants