For this class:
public class Movie {
public int MovieId { get; set; }
public string Title { get; set; }
public int Rating { get; set; }
public int ProducerID { get; set; }
public Producer Producer { get; set; }
}
I just want to know which one will be used as the primary key when Entity Framework maps this class to the corresponding database table?
also which one would be the foreign key?
Related
When I migrate my new models and data I get the following error for multiple foreign keys:
The foreign key property 'FavoriteList.SongId1' was created in shadow
state because a conflicting property with the simple name 'SongId'
exists in the entity type, but is either not mapped, is already used
for another relationship, or is incompatible with the associated
primary key type. See https://aka.ms/efcore-relationships for
information on mapping relationships in EF Core.
Example of my models:
public class FavoriteList
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int MovieId { get; set; }
[ForeignKey("MovieId")]
public int SongId { get; set; }
[ForeignKey("SongId")]
public int CustomerId { get; set; }
[ForeignKey("CustomerId")]
public virtual Movie Movie { get; set; }
public virtual Song Song { get; set; }
public virtual Customer Customer { get; set; }
}
I am not sure why I am getting this error:
System.InvalidOperationException: 'The relationship from 'Insured' to 'Quote.Insureds' with foreign key properties {'InsuredID' : string} cannot target the primary key {'InsuredID' : string, 'ProducerID' : string} because it is not compatible. Configure a principal key or a set of compatible foreign key properties for this relationship.'
I am trying to configure two keys in the Quote model, one for my Insured model and one for my Producer. I attempted to only have one key before and just use foreign keys but that didnt work.
public class Producer
{
[Key]
public string ProducerID { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public class Insured
{
[Key]
public string InsuredID { get; set; }
public string NamedInsured { get; set; }
public string Address1 {get; set;}
public class Quote
{
public string InsuredID { get; set; }
public string ProducerID { get; set; }
[ForeignKey("ProducerID")]
public IList<Producer> Producers { get; set; }
[ForeignKey("InsuredID")]
public IList<Insured> Insureds { get; set; }
In my DB context:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Quote>().HasKey(q => new { q.InsuredID , q.ProducerID});
It is not possible to reference an array with a key
It needs to be an object rather than a collection.
public class Quote
{
public string InsuredID { get; set; }
public string ProducerID { get; set; }
[ForeignKey("ProducerID")]
public Producer Producer { get; set; }
[ForeignKey("InsuredID")]
public Insured Insured { get; set; }
}
I have 2 classes which have a many to many relation.
public class Document
{
public int Id { get; set; }
public string Name { get; set; }
public bool AvailableOffline { get; set; }
public string URL { get; set; }
public virtual ICollection<Profile> Profiles { get; set; }
}
public class Profile
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Document> Documents { get; set; }
}
On each profile I wish to have a SortOrder field for each document. So I made the joined table explicit in another class
public class ProfileDocuments
{
[Key, Column(Order = 0)]
public int DocumentId { get; set; }
[Key, Column(Order = 1)]
public int ProfileId { get; set; }
public int SortOrder { get; set; }
[ForeignKey("DocumentId")]
public virtual Document Document { get; set; }
[ForeignKey("ProfileId")]
public virtual Profile Profile { get; set; }
}
But when I update the database the table for this last class will not have a column for SortOrder. It only holds the 2 foreign keys. How can I tell EF to generate this table with my column?
When a junction table in a many-to-many association should contain more information than just the two foreign keys, it's no longer possible to map the association as a 'pure' many-to-many (with hidden junction class).
You need an explicit class in the class model to address the extra information (as you already found out), but this also changes the association into 1-n-1:
class Document
{
...
public virtual ICollection<ProfileDocument> ProfileDocuments { get; set; }
}
class Profile
{
...
public virtual ICollection<ProfileDocument> ProfileDocuments { get; set; }
}
I'm creating a database with serveral classes as children of other classes. Writing with foreign keys works fine however when i try to get the data back it throws the error:
An unhandled exception of type 'SQLiteNetExtensions.Exceptions.IncorrectRelationshipException' occurred in SQLiteNetExtensions.dll
Additional information: MatchDetail.timeline: At least one entity in a OneToOne relationship must have Foreign Key
This is my creation code:
SQLiteConnection db = new SQLiteConnection(new SQLite.Net.Platform.Win32.SQLitePlatformWin32(), "Matches.db3");
db.CreateTable<ParticipantIdentity>();
db.CreateTable<MatchDetail>();
db.CreateTable<Timeline>();
db.InsertWithChildren(md, true);
var m = db.GetWithChildren<MatchDetail>(matchId, true);
And my class:
[Table("Matches")]
public class MatchDetail
{
[PrimaryKey]
public long matchId { get; set; }
public int mapId { get; set; }
[JsonConverter(typeof(DateTimeConverterFromLong))]
public DateTime MatchCreation { get; set; }
public long matchDuration { get; set; }
public MatchMode matchMode { get; set; }
public MatchType matchType { get; set; }
public string matchVersion { get; set; }
public string platformId { get; set; }
public Queuetype queueType { get; set; }
public Region region { get; set; }
public Season season { get; set; }
[ForeignKey(typeof(Timeline), Name = "TimelineId"), Indexed]
public int timelineId { get; set; }
[OneToOne("TimelineId", CascadeOperations = CascadeOperation.All)]
public Timeline timeline { get; set; }
[ForeignKey(typeof(ParticipantIdentity), Name = "ParticipantId"), Indexed]
public int participantIdentitiesId { get; set; }
[ManyToOne("ParticipantId", CascadeOperations = CascadeOperation.All)]
public List<ParticipantIdentity> participantIdentities { get; set; }
}
The other classes are just an id and some other basic types, I've been trying to work this out but it just doesnt want to work.
Edit:
[ForeignKey(typeof(ParticipantIdentity))]
public int participantIdentitiesId { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<ParticipantIdentity> participantIdentities { get; set; }
With error:
An unhandled exception of type 'SQLiteNetExtensions.Exceptions.IncorrectRelationshipException' occurred in SQLiteNetExtensions.dll
Additional information: MatchDetail.participantIdentities: Unable to find foreign key for OneToMany relationship
You are manually specifying that the foreign key is named 'TimelineId' but in reality the foreign key is named 'timelineId' (note capitalization of the first letter).
Change this:
[ForeignKey(typeof(Timeline), Name = "TimelineId"), Indexed]
public int timelineId { get; set; }
[OneToOne("TimelineId", CascadeOperations = CascadeOperation.All)]
public Timeline timeline { get; set; }
To this:
[ForeignKey(typeof(Timeline)]
public int timelineId { get; set; }
[OneToOne(CascadeOperations = CascadeOperation.All)]
public Timeline timeline { get; set; }
Explicitly declaring the foreign key name can lead to refactoring issues, so this is the recommended way unless otherwise is strictly required.
The other relationship is declared as a ManyToOne but it's in fact a OneToMany. To make it work you have to change the attribute type and move the foreign key to the other end.
Change the relationship from:
[ForeignKey(typeof(ParticipantIdentity), Name = "ParticipantId"), Indexed]
public int participantIdentitiesId { get; set; }
[ManyToOne("ParticipantId", CascadeOperations = CascadeOperation.All)]
public List<ParticipantIdentity> participantIdentities { get; set; }
With this:
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<ParticipantIdentity> participantIdentities { get; set; }
And add the foreign key to MatchDetail to the ParticipantIdentity class:
[ForeignKey(typeof(MatchDetail)]
public int matchDetailId { get; set; }
Take a look at the SQLite-Net Extensions documentation and sample project for more examples.
I have two model class, where I want to make one-to-one relation. When I make migration, I get an error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Uzytkownik_dbo.UserProfile_UserId". The conflict occurred in
database "db_wydarzenia", table "dbo.UserProfile", column 'UserId'.
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
[Table("Uzytkownik")]
public class Uzytkownik
{
[Key]
public int UzytkownikID { get; set; }
public int UserId { get; set; }
public string Imie { get; set; }
public string Nazwisko { get; set; }
public string Telefon { get; set; }
public string Email { get; set; }
[ForeignKey("UserId")]
public UserProfile UserProfile { get; set; }
}
EDIT:
Problem solved :)
I remove all data from uzytkownik table and it's go.
If you want one-to-one - you cannot have both the primary-key and the foreign-key specified. One-to-one is modeled via primary-keys (pk == pk), otherwise it becomes 'multiplicity' (and just typical one-to-many).
To get what you want just remove your other PK - and user UserId as both primary and fk...
[Table("Uzytkownik")]
public class Uzytkownik
{
// [Key] public int UzytkownikID { get; set; }
[Key]
public int UserId { get; set; }
[ForeignKey("UserId")]
public UserProfile UserProfile { get; set; }
}