I have a simple relationship. A campaign is linked to two Pages. A page can only be linked to one campaign. But I keep running into this error:
System.Data.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'Page_Campaign_Source' in relationship 'Page_Campaign'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
I went looking through some example codes and tutorials while comparing it to my code but I can't find a mistake.
public class Campaign
{
[Key()]
public int Campaignid { get; set; }
public string Name { get; set; }
public virtual Page LandingPage { get; set; }
public virtual RedeemPage RedeemPage { get; set; }
}
public class Page
{
[Key()]
public int PageContentId { get; set; }
public string Logo { get; set; }
public string Css { get; set; }
[ForeignKey("Campaign")]
public int campaignID { get; set; }
public virtual Campaign Campaign { get; set; }
}
Followed Eranga's reply and used the Fluent API instead but now I'm getting:
An error occurred while saving entities that do not expose foreign key properties for their relationships
The Data annotations mapping is confusing in this scenario. Use the Fluent API to configure. Remove the data annotations for navigational property mapping and use fluent API as follows.
class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Campaign>().HasRequired(x => x.LandingPage)
.WithMany();
modelBuilder.Entity<Page>().HasRequired(x => x.Campaign)
.WithMany()
.HasForeignKey(x => x.campaignID);
base.OnModelCreating(modelBuilder);
}
}
Edit
The problem after setting WillCascadeOnDelete(false)
is that both Campaign
and Page
has auto incremented PKs and you have a 1-to-1 mapping. Hence to save one record it needs the Id of the other inserted row and that other row need the id of the 1st row.
You can either change the PK to be a GUID or make 1 FK to be nullable and call to SaveChanges
twice. Eg
Changing the relationship to nullable
modelBuilder.Entity<Campaign>().HasOptional(x => x.LandingPage)
.WithMany();
using(var scope = new TransactionScope())
{
context.Campaigns.Add(campaign);
context.SaveChanges();
page.CampaignId = campaign.CampaignId;
context.Pagess.Add(page);
context.SaveChanges();
scope.Complete();
}
I think you should have a collection of pages in your campaign, instead of the 2 children-entities,
has been a while since I've last coded in MVC but if I recall correctly it should be something like:
public virtual Collection<Page> pages
in which you then put your 2 pages