Ron
Ron

Reputation: 21

EFCore owned model has object property mapped to foreignKey

I have a model in which 3 classes (part of the complete model)
I want to have 2 model classes to the same table(split table), when the owned class has ForeignKey to the third class.
but when I tried to configure the ForeignKey I got error: (0x80131904): Invalid column name 'Customer_city_id'.
I can't change the model or the tables, but only the context.
model:

public class City
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string District { get; set; }
}

public class Customer
{
    public string? Id { get; set; }
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public City? City { get; set; }
}

public class Order
{
    public int Id { get; set; }//OrderId
    public Customer Customer { get; set; }       
    //more owntype properties
}

tables:

tbl_customers
-----------------------------------------------------------
id | customer_id | customer_first_name | customer_last_name
tbl_city
-----------------------------------------------------------
city| city_desc| dist

Context:

public class EntityContext: DbContext
{
    public DbSet<Order> Orders { get; set; }
    //public DbSet<Customer> Customers { get; set; }
    

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseSqlServer("myConnectionString");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        
        modelBuilder.Entity<City>(c =>
        {
            c.ToTable("tbl_city")
            .HasKey(c=>c.Id);

            c.Property(c => c.Id)
            .HasColumnName("city");

            c.Property(c => c.Name)
            .HasColumnName("city_desc");

            c.Property(c => c.District)
            .HasColumnName("dist");
        });
        modelBuilder.Entity<Order>(c =>
        {
            c.ToTable("tbl_customers");
            c.Property(c=>c.Id).HasColumnName("id");
            c.OwnsOne(p => p.Customer, s =>
                {
                    s.ToTable("tbl_customers");
                    s.Property(c => c.Id)
                    .HasColumnName("customer_id");
                    s.Property(c => c.FirstName)
                        .HasColumnName("customer_first_name");
                    s.Property(c => c.LastName)
                        .HasColumnName("customer_last_name");

                //---------get error->

                // s.HasOne<City>()
                //  .WithMany("city")
                //  .HasForeignKey("city_id");

                
                });
        }); 

        
    }
}

but I get Error:

(0x80131904): Invalid column name 'Customer_city_id'.
   at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__188_0(Task`1 result)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)                    

Upvotes: 0

Views: 608

Answers (1)

Simon B
Simon B

Reputation: 92

From the Microsoft documentation of owned types:

EF Core allows you to model entity types that can only ever appear on navigation properties of other entity types. These are called owned entity types. The entity containing an owned entity type is its owner. Source

So, no HasOne configurations are allowed on such properties, because this would mean they could appear on an entity that does not own them, which would defeat the purpose.

Instead, i would advise using HasOne/WithMany instead of OwnsOne, because OwnsOne means the customer is part of the Order, and cannot exist without it (which is probably not what you want).

EDIT: In EF Core, the Model is defined via the Context, so you can change the model, the tables and everything else only by having access to the context.

Also, could you clarify what you mean with 'have 2 model classes to the same table'? I understand you want one Table holding the order AND customer information, with a foreign key to a city. But as explained, this would mean that the customer would only be able to exist as a part of an order, and thus cannot exist independently. If that is what you want though, you could move the HasOne(customer => customer.City) call to the order entity definition, in which case there should be no error.

Upvotes: 0

Related Questions