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

Shadow property is not created by .ForeignKey(Type, string) #3576

Closed
sebastienros opened this issue Oct 27, 2015 · 4 comments
Closed

Shadow property is not created by .ForeignKey(Type, string) #3576

sebastienros opened this issue Oct 27, 2015 · 4 comments
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

@sebastienros
Copy link
Member

... and is not taken into account if defined late in the Model.

Repro: this code should not throw an exception, but actually complains that DocumentId is not found or defined as a shadow property

    class Program
    {
        static void Main(string[] args)
        {
            var builder = new DbContextOptionsBuilder();
            var conventionBuilder = new CoreConventionSetBuilder();
            var modelBuilder = new ModelBuilder(
                conventionBuilder.CreateConventionSet()
                );

            modelBuilder.Entity<Document>(x =>
            {
                // I want the DocumentId FK on the PersonByName table
                x.HasOne(typeof(PersonByName), "PersonByName")
                    .WithOne()
                    .ForeignKey(typeof(PersonByName), "DocumentId");
            });

            modelBuilder.Entity<PersonByName>(x =>
            {
                // Defines shadow property DocumentId explicitely
                x.Property(typeof(int), "DocumentId");
            });

            modelBuilder.Validate();

            builder.UseModel(modelBuilder.Model);
            var dbFileName = Path.GetTempFileName();
            builder.UseSqlite(@"Data Source=" + dbFileName + ";Cache=Shared");

            // Ensure the database is created
            var dbContext = new DbContext(builder.Options);
            dbContext.Database.EnsureCreated();

            try {
                var p1 = new PersonByName { Name = "Bill" };
                var d1 = new Document { PersonByName = p1 };
                dbContext.Set<PersonByName>().Add(p1);
                dbContext.Set<Document>().Add(d1);
                dbContext.SaveChanges();

                IQueryable<Document> documents = dbContext.Set<Document>();
                Console.WriteLine(1 == documents.Count());

                Console.WriteLine(null != documents
                    .Where(x => x.PersonByName.Name == "Bill").FirstOrDefault());


            }
            finally
            {
                dbContext.Dispose();
                File.Delete(dbFileName);
            }
        }
    }

    public class Document
    {
        public int Id { get; set; }
        public PersonByName PersonByName { get; set; }
    }

    public class PersonByName
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
@rowanmiller rowanmiller changed the title Shadow property is not created as advertized Shadow property is not created by .ForeignKey(Type, string) Oct 27, 2015
@rowanmiller rowanmiller added this to the 7.0.0 milestone Oct 27, 2015
@smitpatel
Copy link
Contributor

The above exception is thrown when you try to use a shadow property which is not defined in the model in one of the functions - HasKey, HasIndex & HasForeignKey with string based arguments. There are 2 reasons for which above methods throw exception.

  1. When you try to use a property which is not defined yet and does not exist on clr type, EF does not know anything about the property other than name. Especially, the clr type is important information while creating relationships. So it is not easy to assign a temporary type to the property and create it. Also it is hard to keep track that property was created using such function and should be plugged in by user later.
  2. Since methods are string based, it is prone to typing errors. Suppose user spells the property wrongly and EF creates the property and the model wouldn't work as expected, it would not be easy to find out the issue for large models.

Therefore above methods require you to define the shadow properties in the model before using them.

For the case of HasForeignKey - it becomes bit simpler in the sense that you can get the clr types for the properties from the referenced primary key. In that case EF can create properties with those types for user.
@rowanmiller - Should we create properties from HasForeignKey using this logic?

@smitpatel smitpatel removed this from the 7.0.0 milestone Nov 10, 2015
@smitpatel
Copy link
Contributor

Cleared milestone to decide if we should create shadow properties or not.

@rowanmiller rowanmiller added this to the 7.0.0 milestone Nov 17, 2015
@rowanmiller
Copy link
Contributor

@smitpatel we should do this.
@AndriySvyryd thought there may have already been an issue tracking this, but I was not able to find it

@AndriySvyryd
Copy link
Member

That would be #1124

@smitpatel smitpatel modified the milestones: 7.0.0-rc2, 7.0.0 Nov 21, 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