How to map child entity to parent entity without introducing primitive type parent linker in child entity?

19,671

Solution 1

I don't understand why do you use fluent mapping? Your model should be mapped by default conventions. If you want to map it with fluent mapping use:

modelBuilder.Entity<Product>()
            .HasMany(x => x.ProductPriceList) // Product has many ProductPricings
            .WithRequired(y => y.Product)     // ProductPricing has required Product
            .Map(m => m.MapKey("ProductId")); // Map FK in database to ProductId column

Solution 2

This has the correct answer:

http://agilenet.wordpress.com/2011/04/18/entity-framework-code-first-specify-foreign-key-name-in-one-to-many-relationship-with-fluent-api/

I almost got it:

modelBuilder.Entity<ProductPricing>()
    .HasRequired(x => x.Product)
    .WithMany()
    .Map(x => x.MapKey("ProductId"));

I just forgot to put the principal's dependent(i.e. ProductPriceList. I hope I'm getting the right terminology, wanted to stay away from parent child terminology ^_^):

modelBuilder.Entity<ProductPricing>()
    .HasRequired(x => x.Product)
    .WithMany(x => x.ProductPriceList)
    .Map(x => x.MapKey("ProductId"));

Entity Framework's Fluent Mapping is hardly fluent, there's some stutter you could unwittingly commit if you are not very familiar with each method's nuances :-) Lookie that, I almost got it correct. Passing both ProductPricing and ProductPriceList look redundant, hardly intuitive.

EF's fluent mapping is hardly a good fluent(of which intuitiveness should be an innate quality) interface citizen, isn't it?

Share:
19,671
Hao
Author by

Hao

Updated on June 22, 2022

Comments

  • Hao
    Hao almost 2 years

    I have these classes:

    public class Product
    {
        [Key]
        public virtual int ProductId { get; set; }
        public virtual string ProductName { get; set; }
        public virtual string Category { get; set; }
    
        public virtual IList<ProductPricing> ProductPriceList { get; set; }
    
    
        [Timestamp]
        public virtual byte[] Version { get; set; }
    }
    
    public class ProductPricing
    {        
    
        // no ProductId here
        public virtual Product Product { get; set; }
    
        [Key]
        public virtual int ProductPricingId { get; set; }
    
        public virtual DateTime EffectiveDate { get; set; }
        public virtual decimal Price { get; set; }
    
    
    }
    

    This is my modelBuilder:

    modelBuilder.Entity<Product>().
        HasMany(x => x.ProductPriceList)
       .WithRequired()
       .HasForeignKey(x => x.Product);
    

    This is the error:

    The foreign key component 'Product' is not a declared property on type 'ProductPricing'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.

    UPDATE

    I've tried the following, corresponding errors below the code

    modelBuilder.Entity<Product>()
        .HasMany(x => x.ProductPriceList)
        .WithRequired();
    

    {"Invalid column name 'Product_ProductId1'.\r\nInvalid column name 'Product_ProductId'.\r\nInvalid column name 'Product_ProductId1'."}

    modelBuilder.Entity<Product>()
        .HasMany(x => x.ProductPriceList)
        .WithRequired()
        .Map(x => x.MapKey("ProductId"));
    

    {"Invalid column name 'Product_ProductId'."}

    modelBuilder.Entity<Product>()
        .HasMany(x => x.ProductPriceList)
        .WithRequired(x => x.Product);
    

    {"Invalid column name 'Product_ProductId'.\r\nInvalid column name 'Product_ProductId'."}

    modelBuilder.Entity<Product>()
        .HasMany(x => x.ProductPriceList)
        .WithRequired(x => x.Product)
        .Map(x => x.MapKey("ProductId"));
    

    {"Multiplicity constraint violated. The role 'Product_ProductPriceList_Source' of the relationship 'TestEfCrud.Mappers.Product_ProductPriceList' has multiplicity 1 or 0..1."}

    If it could help, here's the DDL:

    create table Product
    (
    ProductId int not null identity(1,1) primary key,
    ProductName varchar(100) not null,
    Category varchar(100) not null,
    Version rowversion not null
    );
    
    create table ProductPricing
    (
    ProductId int not null references Product(ProductId),
    ProductPricingId int identity(1,1) not null primary key,
    EffectiveDate datetime not null,
    Price decimal(18,6) not null
    );
    

    UPDATE 2

    I've tried this answer, which looks a bit similar to my case, mapping originated from child entity How to map parent column in EF 4.1 code first

    However, using this:

    modelBuilder.Entity<ProductPricing>()
        .HasOptional(x => x.Product)
        .WithMany()
        .Map(x => x.MapKey("ForeignKeyColumn"));
    

    and this:

    modelBuilder.Entity<ProductPricing>()
        .HasRequired(x => x.Product)
        .WithMany()
        .HasForeignKey(x => x.Product);
    

    Both resulted to this error:

    {"Invalid column name 'Product_ProductId1'.\r\nInvalid column name 'Product_ProductId1'.\r\nInvalid column name 'Product_ProductId1'."}