Question

I have a Product class:

public class Product
{
    public int ID { get; set; }

    [Required]
    public string Name { get; set; }
    public decimal Price { get; set; }

    public Offer Offer { get; set; }
}

And an Offer class:

public class Offer
{
    public int ID { get; set; }

    [Required]
    public DateTime DateFrom { get; set; }
    public DateTime DateTo { get; set; }
    public decimal OfferPrice { get; set; }
    public Product Product { get; set; }
}

Basically want I want to achieve is when an offer is added a Product is related to this Offer. So an Offer always has a Product but a Product does not always need an Offer. If the Product does have an Offer I'd like to be able to access it through Product.Offer, but in this setup I get the following error message when updating the database:

Unable to determine the principal end of an association between the types 'WebshopISEC.Models.Offer' and 'WebshopISEC.Models.Product'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

I've tried a lot of things (data annotations and Fluent API) and searched endlessly but I cannot seem to solve this issue. A Fluent API approach I've tried:

modelBuilder.Entity<Offer>()
            .HasRequired(x => x.Product)
            .WithOptional(x => x.Offer);

But this worked to no avail, how do I assign a Principal End? And to what class?

Était-ce utile?

La solution

Try this:

public class Product
{
    public int ID { get; set; }

    [Required]
    public string Name { get; set; }
    public decimal Price { get; set; }

    public Offer Offer { get; set; }
}

public class Offer
{
    [ForeignKey("Product")]
    public int ID { get; set; }

    [Required]
    public DateTime DateFrom { get; set; }
    public DateTime DateTo { get; set; }
    public decimal OfferPrice { get; set; }
    public Product Product { get; set; }
}

Autres conseils

When you have a One-to-One relation, one entity must principal and the other one must be the dependent. In this case I recommend you to ensure that the ProductId is FK and PK in Offer, by using data-anotations just like this:

    public class Product
    {
        public int ID { get; set; }
        [Required]
        public string Name { get; set; }
        public decimal Price { get; set; }
        public Offer Offer { get; set; }
    }

    public class Offer
    {
        public int ID { get; set; }
        [Required]
        public DateTime DateFrom { get; set; }
        public DateTime DateTo { get; set; }
        public decimal OfferPrice { get; set; }
        [Required]
        public Product Product { get; set; }
    }

On the other hand, you know more about your project but I will also recommend you using a 1:N relation. Hope it worked.

I had a similar error message for a one to many relationship. I had forgotten to explicitly use a ForeignKey attribute on my parent property. Then when I did try to add the property, I got a migration that would not run. I was able to work around the error by editing the migration

public override void Up()
{

    //DropIndex("dbo.PurchaseManifestLines", new[] { "PurchaseOrderLineId" });
    //RenameColumn(table: "dbo.PurchaseManifestLines", name: "PurchaseOrderLineId", newName: "PurchaseOrderLine_Id1");
    //AddColumn("dbo.PurchaseManifestLines", "PurchaseOrderLine_Id", c => c.Int(nullable: false));
    //AlterColumn("dbo.PurchaseManifestLines", "PurchaseOrderLine_Id1", c => c.Int());
    //CreateIndex("dbo.PurchaseManifestLines", "PurchaseOrderLine_Id1");
    // gives error Column names in each table must be unique. Column name 'PurchaseOrderLine_Id' in table 'dbo.PurchaseManifestLines' is specified more than once.


    //replaced with 
    DropIndex("dbo.PurchaseManifestLines", new[] { "PurchaseOrderLineId" });
    DropColumn("dbo.PurchaseManifestLines", "PurchaseOrderLineId");

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top