0

I'm getting a standard 1:1 Entity error in my MVC app:

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

But, the error is being thrown for a different area and namespace than that for which the MVC controller is called. I've reviewed my relationships based on multiple Stack Overflow questions/answers (many duplicates) and have set up my entities correctly for both Areas.

The error is being thrown from a SyncServer controller for the Fulfillment namespace. The entire Fulfillment Area in the website is error-free -- hence, the relationships are correct (full CRUD available).

But, when navigating the SyncServer MVC Area of the website, I get errors thrown for the Fulfillment entities. The Fulfillment Area came second in the development and the same Sync Server Area code runs in production without issues. Therefore, the Sync Server entities are also set up correctly. With the same SyncServer code running correctly in isolation and the Fulfillment running in combination as a 2nd area, each set of entities seems to be set up correctly. So perhaps there's some type of unintended crossover.

Each Area has it's own registration class with explicitly defined namespaces, for example:

// AreaName = Fulfillment
context.MapRoute(
      "Fulfillment_default",
      string.Concat(AreaName, "/{controller}/{action}/{id}"),
      new { controller = "Home", action = "Index", id = UrlParameter.Optional },
      new string[] { "ProcessManager.ManagementConsole.Areas.Fulfillment.Controllers.MVC" }
);

and

// AreaName = SyncServer
context.MapRoute(
     "SyncServer_default",
     string.Concat(AreaName, "/{controller}/{action}/{id}"),
     new { controller = "Home", action = "Index", id = UrlParameter.Optional },
     new string[] {"ProcessManager.ManagementConsole.Areas.SyncServer.Controllers.MVC"}
);

Fulfillment Definition:

namespace ProcessManager.ManagementConsole.Areas.Fulfillment.Models.API {
    [Table("OrderBook")]
    public partial class OrderBook
    {
        public OrderBook() {}

        [Key]  // I've tried omitting this and defining exclusively in FluentAPI
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }

        ...

        [ForeignKey("OrderBookID")]  // I've tried omitting this
        public virtual OrderData OrderData { get; set; }
    }

    [Table("OrderData")]
    public partial class OrderData
    {
        public OrderData() { }

        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int OrderBookID { get; set; }

        ...

        [ForeignKey("OrderBookID")]  // I've tried omitting this and defining exclusively in FluentAPI
        public virtual OrderBook OrderBook { get; set; }
    }
}

Fulfillment OnModelCreating:

 modelBuilder.Entity<OrderBook>()
        .HasRequired(c1 => c1.OrderData)
        .WithRequiredPrincipal(c2 => c2.OrderBook);

SyncServer Definition:

namespace ProcessManager.ManagementConsole.Areas.SyncServer.Models.MVC {
    [Table("BAppJobOrderBook")]
    public partial class BAppJobOrderBook
    {
        [StringLength(50)]
        public string ID { get; set; }

        ...

        (no relationships)
    }
}

The only commonality that makes me think there's some crossover is the controller names, although they are still different (plurality).

namespace ProcessManager.ManagementConsole.Areas.SyncServer.Controllers.MVC {
public class OrderBookController : Controller
{
    private Models.MVC.SyncServer db = new Models.MVC.SyncServer();

and

namespace ProcessManager.ManagementConsole.Areas.Fulfillment.Controllers.MVC {
public class OrderBooksController : Controller
{
    private Models.MVC.Fulfillment db = new Models.MVC.Fulfillment();

And finally, the code where the error appears in the SyncServer view for OrderBook (just an example, all SyncServer views throw an error in the async Task<ActionResult> Index method).

var objs = from s in db.BAppJobOrderBooks select s;

So, what could cause each area run in isolation to run properly and when running on the same app in different area to throw an error? Why is there an overlap when all the namespaces are explicitly defined and separated (models, controllers and views)? What am I missing?

Greg
  • 119
  • 1
  • 10

1 Answers1

0

As you are probably aware, this error is caused by your entities not having a clear relationship as far as EF is concerned, so I wouldn't worry too much about the MVC side of things- this is trouble in your data store. In a situation where the same code works differently on different servers I would start by confirming that all my migrations have been run everywhere. Your model doesn't describe which out of the OrderBook and OrderData is principal so the only place that gets set is from the fluent code in OnModelCreating.

This suggests to me one of two things- either your OnModelCreation code is being skipped for some reason (check if a breakpoint on there is hit) or your database does not correctly match your models. If you didn't run the model creation migration locally ( or you already ran it before changing it and there is an entry in your migration history table so EF thinks it doesn't need to run it again ) then there may be a mismatch between what EF expects to find there and what shows up. Another useful strategy can be to spin up a new database from scratch and check whether that works correctly.

Either way the core of your problem is that relationship and by focusing your attention on the EF side of things you should be able to iron it out reasonably easily.

glenatron
  • 11,018
  • 13
  • 64
  • 112
  • 1
    You're right, I was looking in the wrong places for the problem. First, I didn't have a SetInitializer call in the DbContext subclass initializer. I was mixing FluentAPI (for relationships) and Data Annotation. It didn't evenrealize that the OnModelCreating was never being called (where I explicitly included principal info). Second, some scaffolding error on my part ended up putting an entity for one model on the other incorrect model. When the SyncServer model was built, it had no idea about the relationships for the Fulfillment model. Thanks for helping to set me down the right path. – Greg Sep 04 '17 at 10:16