Question

I have a quick question about setting up the mappings between [Order Details], [Products] and [Orders] in the Northwind datbase.

[Order Details] has no primary key, and looks like this

[Order Details]
OrderId (int)
ProductId (int)
...

So my question is how do I (and can I) set up my OrderDetails class to work like this?

public class OrderDetails
{
    public virtual Order Order { get; set; }
    public virtual Product Product { get; set; }
    public Decimal UnitPrice { get; set; }
    public int Quantity { get; set; }
    public Decimal Discount { get; set; }
}

My data context looks like this

public class NorthwindDb : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<Category> Categories { get; set; }
    public DbSet<Order> Orders { get; set; }
    public DbSet<OrderDetails> OrderDetails { get; set; }
    public DbSet<Customer> Customers { get; set; }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new OrderDetailsConfiguration());
    }

    public static void InitializeBecauseOfThatWeirdMetaDataThingThatIDontUnderstandYet()
    {
        Database.SetInitializer<NorthwindDb>(null);
    }

}

And My OrderDetailsConfiguration (empty because I don't know what I'm doing)

public class OrderDetailsConfiguration : EntityConfiguration<OrderDetails>
{
    public OrderDetailsConfiguration()
    {
        //HasKey(x => x.Order.OrderId);
        //HasKey(x => x.Product.ProductId);
    }
}

Any hints or ideas would be great.

Was it helpful?

Solution

First you would have to explicitly put in the PKs and FKs inside OrderDetails class:

public class OrderDetails 
{        
    public int OrderID { get; set; }
    public int ProductID { get; set; }

    public virtual Order Order { get; set; }
    public virtual Product Product { get; set; }

    public Decimal UnitPrice { get; set; }
    public int Quantity { get; set; }
    public Decimal Discount { get; set; }
}

Then with the following code you can specify the PKs for OrderDetailsConfiguration class:
(Please note that in Northwind database both OrderID and ProductID are PKs for OrderDetails table).

public class OrderDetailsConfiguration : EntityConfiguration<OrderDetails> 
{
    public OrderDetailsConfiguration() 
    {
        HasKey(od => new 
        {
            od.ProductID,
            od.OrderID
        });
    }
}

And also you can use RecreateDatabaseIfModelChanges strategy to force your database to be recreated every time you change the class model:

Database.SetInitializer<NorthwindDb>(
        new RecreateDatabaseIfModelChanges<NorthwindDb>());

The interesting point is that once you made these changes EF will automatically infer the FKs from OrderDetails class and create the relationships to Orders and Products table on OrderID and ProductID based on the Conventions for Code First:

Code First will infer that any property named <navigation property name><primary key property name> (i.e. ProductsProductID), <principal class name><primary key property name> (i.e. ProductProductID) or <primary key property name> (i.e. ProductID), with the same data type as the primary key, represents a foreign key for the relationship. If multiple matches are found then precedence is given in the order listed above. Foreign key detection will not be case sensitive.

OTHER TIPS

Mark key fields with [Key] attribute. You will need to add [Column(Order = x)] in case of compound keys, x = 0, 1, 2, ... Numbering can start from any number https://msdn.microsoft.com/en-us/data/jj591583.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top