Hopefully, one of you more experienced developers can help with this (I'm still learning)
I have an issue with a shadow key being created, I have this class;
public class ProductInterest
{
public int Id { get; set; }
public int ProductInterestId { get; set; }
[Required(ErrorMessage = "Product Interest Name is required")]
[DisplayName("Product of Interest")]
public string ProductInterestName { get; set; }
}
The data this form collects I would like to use this as a dataset in two dropdown lists, so i created this;
public class Lead
{
//other properties
[Display(Name = "Product Interest")]
public int? ProductInterestId { get; set; }
[Display(Name = "Product Interest 2")]
public int? ProductInterestId2 { get; set; }
public ProductInterest? ProductInterest { get; set; }
public List? ProductInterestsList { get; set; }
public List? ProductInterests2List { get; set; }
//other lists
}
after the migration, I got the error;
"There are multiple relationships between 'ProductInterest' and 'Lead' without configured foreign key properties. This will cause Entity Framework to create shadow properties on 'ProductInterest' with names dependent on the discovery order. Consider configuring the foreign key properties using the [ForeignKey] attribute or in 'OnModelCreating'.
Microsoft.EntityFrameworkCore.Model.Validation[10625]"
I have tried
public class Lead
{
// ... other properties ...
public int? ProductInterestId { get; set; }
[ForeignKey("ProductInterestId")]
public ProductInterest ProductInterest { get; set; }
public int? ProductInterestId2 { get; set; }
[ForeignKey("ProductInterestId2")]
public ProductInterest ProductInterest2 { get; set; }
// ... other properties ...
}
But got the same result, so after many hours I gave up and updated the database to see what would happen and noticed in the database that it had created columns in the dataset table (product interest) two columns for LeadId1 & LeadId2. I don't need this to be logged here as the Lead table is catching which selection has been made.
After a little digging and some help from a well-known AI helper, I tried this;
modelBuilder.Entity()
.HasOne(l => l.ProductInterest)
.WithMany()
.HasForeignKey(l => l.ProductInterestId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity()
.HasOne(l => l.ProductInterest2)
.WithMany()
.HasForeignKey(l => l.ProductInterestId2)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity()
.HasOne(l => l.LeadSource)
.WithMany()
.HasForeignKey(l => l.LeadSourceId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity()
.HasOne(l => l.LeadType)
.WithMany()
.HasForeignKey(l => l.LeadTypeId)
.OnDelete(DeleteBehavior.Restrict);
Although the program is working fine I know that it's not correct and, on this long and at times painful journey of learning I would like to try and understand what I'm doing wrong
any help or advice would be appreciated.
Sam HobbsPosted Nov 29, 2023, 9:42 PM
Yes this stuff can be frustrating. I assume you are using Code First.
Something I do sometimes is I create the database the way I want it then use Database First. Microsoft does not support Database First anymore from Visual Studio but we can use EF from a
dotnetcommand to do it. You can create a console application for just getting the output to see what the command does. Create the project in VS (I am not sure but I think you need to add the EF Nuget package) and then in a command prompt go to the project directory then issue the following command.Note that that is using SQLite, you need to change it appropriately. In that %1 (for use in a cmd file) is the Data Source; for SQLite it is the filename with path. The output is put in the
Modelsdirectory.Sam HobbsPosted Dec 1, 2023, 5:59 AM
I am sorry, I do not understand the question.
Yes, EF makes assumptions. For example it assumes that a field called
Idis the primary key. If you want something different from any assumption then you can specify what you need explicitly.I do not know what you mean byit's not the way in which I have created them. EF attempts to determine what you need based on what you provide it.
I see you have 4
modelBuilder.Entity() statements. Are you using all 4? I think you need only one (for each entity).Probably it would help if you specified what the database definition is that you need. Something important is the relationships. Do you need on-to-one, one-to-many, many-to-one or many-to-many? Would each product would have many leads or just one lead? Would each lead have many products or just one product?
SpencerPosted Nov 30, 2023, 12:58 PM
Hi Sam,
Thank you, and yes I'm using code first. Just starting out on my journey to learn and although there are a lot of resources online sometimes you can't see the wood for the trees.
am I right in thinking that EF has just assumed the relationships and it's not the way in which I have created them?
When I have a little more experience I will look into the method you mentioned.