I have 4 tables that like thus:
public class Table1
{
public int Id {get;set;}
public string Name {get;set;}
}
public class Table2
{
public int Id {get;set;}
public string Name {get;set;}
public int Table1Id {get;set;}
public virtual Table1 {get; set;}
}
public class Table3
{
public int Id {get;set;}
public string Name {get;set;}
public int Table2Id {get;set;}
public virtual Table2 {get; set;}
}
public class Table4
{
public int Id {get;set;}
public string Name {get;set;}
public int Table3Id {get;set;}
public virtual Table3 {get; set;}
}
And my fluent API is like thus:
modelBuilder.Entity<Table2>().HasRequired(x => x.Table1).WithMany().WillCascadeOnDelete(false);
modelBuilder.Entity<Table3>().HasRequired(x => x.Table2).WithMany().WillCascadeOnDelete(false);
modelBuilder.Entity<Table4>().HasRequired(x => x.Table3).WithMany().WillCascadeOnDelete(false);
When I try to seed the tables, I get this error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Table4_Table3_Table3Id.
The conflict occurred in database MyDb, table "dbo.Table3", column 'Id'.The statement has been terminated."
I cannot see where I am going wrong
do this...
modelBuilder.Entity<Table2>()
.HasRequired(t => t.Table1)
.WithMany() // t => t.AllTable2s)
.HasForeignKey(t => t.Table1ID);
...and above all make it compile ! :) (e.g. public virtual Table1 {get; set;} into public virtual Table1 Table1 {get; set;}
Related
I am using entity framework core 5 query syntax. There are 3 classes which reflect the tables in database.
public class Record { public int RecordID {get; set;} public decimal Amount {get; set} public string AccountName {get; set;} }
public class Dimension { public int DimensionID {get; set;} public string DimensionSymbol {get; set;} }
public class DimensionName { public int ID {get; set;} public string Name {get; set;} }
public class RecordDto { public int ID {get; set;} public string DimensionName {get; set;} }
The aim is to find DimensionName foreach Record. The relationship is as follows. RecordID field is a foreign key for Dimension. So it is easy to find this relationship. The problem is with DimensionName. DimensionID is NOT a foreign key to DimensionName. The logical key is DimensionSymbol which sometimes is a simple text like "200.000B" and sometimes it represents the number like 190. If DimensionSymbol is 190 then this 190 reflects the ID in DimensionName.
My query is as follows.
var query = from r in context.Records
join d in context.Dimensions on r.RecordID equals d.DimensionID
join n in context.DimensionNames on int.Parse(d.DimensionSymbol)\>0 ? int.Parse(d.DimensionSymbol) : 0 equals n.ID
select new RecordDto
{
ID = r.RecordID,
DimensionName = n.Name
}
And it doesn't work. Could you please adjust the code so that it works? Maybe I should configure sth in OnConfiguring method.
I have the following classes: User, Post and UserPost. User and Post have a 1-to-many relationship. There's a third join table called UserPost that tracks the up/down vote each post gets. To ensure each user can only upvote/downvote once, the ID (PK) of this table is a composite key of User and Post ID.
public class User {
public Guid Id {get; set;}
public string UserName {get; set;}
public ICollection<Post> Posts {get; set;}
}
public class Post {
public Guid Id {get; set;}
public string Content {get;set;}
public User User {get; set;}
}
public UserPost {
public Guid Id {get; set;} // This should be a composite key of User ID and Post ID
public Guid PostId {get;set;}
public Guid UserId {get;set;}
public VoteType VoteType {get; set;}
}
public enum VoteType {
Up = 1,
Down = 0
}
In my DB Context class I defined the User/Post relationship like this:
builder.Entity<User>()
.HasMany(u => u.Posts)
.WithOne(p => p.User)
Now I want to define the relationship for the UserPost model but not sure how to go about it. So far I have:
builder.Entity<UserPost>()
.HasKey(x => new { x.UserId, x.PostId })
Does it require anything further?
Write your whole relationship as follows:
public class User
{
public Guid Id {get; set;}
public string UserName {get; set;}
public ICollection<Post> Posts {get; set;}
}
public class Post
{
public Guid Id {get; set;}
public string Content {get;set;}
public Guid UserId {get; set;}
public User User {get; set;}
}
public UserVote // Rename this from UserPost to UserVote to keep naming consistency.
{
public Guid PostId {get;set;}
public Guid UserId {get;set;}
public VoteType VoteType {get; set;}
public Post Post {get; set;}
public User User {get; set;}
}
public enum VoteType {
Up = 1,
Down = 0
}
Now, Fluent API configuration for the UserVote as follows:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<UserVote>(e =>
{
e.HasKey(uv => new { uv.PostId, uv.UserId}); //<-- Here is the composite key.
e.HasOne(uv => uv.Post).WithMany().HasForeignKey(uv => uv.PostId).OnDelete(DeleteBehavior.Restrict);
e.HasOne(uv => uv.User).WithMany().HasForeignKey(uv => uv.UserId).OnDelete(DeleteBehavior.Restrict);
});
}
I have some problems with EF CodeFirst and relations 0/1 to 0/1. I have 3 "tables" that contains another, and this is optional.
It's similar to:
[DataContract]
public class A
{
[DataMember, Key]
public int Id {get;set;}
[DataMember]
public int? IdD
[ForeignKey("idD")]
public virtual D D {get; set;}
}
[DataContract]
public class B
{
[DataMember, Key]
public int Id {get;set;}
[DataMember]
public int? IdD
[ForeignKey("idD")]
public virtual D D {get; set;}
}
[DataContract]
public class C
{
[DataMember, Key]
public int Id {get;set;}
[DataMember]
public int? IdD
[ForeignKey("idD")]
public virtual D D {get; set;}
}
[DataContract]
public class D
{
[DataMember, Key]
public int Id {get;set;}
public virtual A A { get; set; }
public virtual B B { get; set; }
public virtual C C { get; set; }
}
When I try to made the migration, appears the error:
Unable to determine the principal end of an association between the types 'XXXXXX' and 'XXXXXX'.
The principal end of this association must be explicitly configured using either the relationship
fluent API or data annotations.
I try with DataAnnotations and with Fluent API and appears the same error. On Fluent API I try:
with A, B or C class
this.HasOptional(casv => casv.D)
.WithOptionalDependent(e => e.A)//I try with denendent and Principal
.Map(m => m.MapKey("IdD")) // I try without this
.WillCascadeOnDelete(true);
try this, I think it's better looking than your code:
this.HasOptional(casv => casv.D)
.WithOptionalDependent(e => e.A)
.Map(m => m.MapKey("IdD"))
.WillCascadeOnDelete(true);
Hi guys I have a question about EF Fluent API (Code First :P). In my model I have
public class TABLE_A
{
public virtual long Id {get; set;}
....
public virtual TABLE_B MyTableBRef {get; set;}
}
public class TABLE_B
{
public virtual long Id {get; set;}
....
public virtual TABLE_A MyTableARef {get; set;}
}
How am I supposed to map a 0..1 to 0..1 relationship?
In the database on TABLE_B I have a column (FK) that references the PK of TABLE_A.
It is not possible to have navigational properties on both sides if you are using a column other than the PK of TABLE_B.
public class TABLE_A
{
public virtual long Id {get; set;}
}
public class TABLE_B
{
public virtual long Id {get; set;}
....
public virutal TABLE_A MyTableARef {get; set;}
}
public class MyContext : DbContext
{
public DbSet<TABLE_A> As { get; set; }
public DbSet<TABLE_B> Bs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<TABLE_B>()
.HasRequired(b => b.MyTableARef)
.WithMany()
.Map(b => b.MapKey("FK_Column_name));
}
}
If the PK of TABLE_B is also a FK to TABLE_A then you can use shared PK mapping with navigational properties on both sides.
Edit:
You can use Shared PK mapping as follows
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<TABLE_B>()
.HasRequired(b => b.MyTableARef)
.WithOptional(a => a.MyTableBRef);
}
The Id of TABLE_B is also an FK to TABLE_A.
How o define one to many relationship in EF with different primary and foreign key name
UPDATED
Public class Tb1
{
[Key]
public int ID{get; set;} // primary
**public int foreignKey{get; set;} //foreign key**
public string name{get; set;}
[Foreign("foreignKey")]
public virtual ICollection<Tb2> Tb2{ get; set; }
}
Public class Tb2
{
[Key]
public int ID {get; set;} //primary
public int tb1ID {get; set}
public string address {get; set;}
}
Here i want one to many relationsip on Primary key: foreignKey at TB1
foreign kye: tb1ID at TB2
HOW??
My Nomal approach would be to include the navigation property as well. So I would change Tb2 like this:
Public class Tb2
{
[Key]
public int ID {get; set;} //primary
public int Tb1ID {get; set;} //notice I changed case on this variable as well
public Tb1 Tb1 {get; set;} //this is the new variable
public string address {get; set;}
}
Code first should be able to automatically understand the relationship now. If you don't want the Tb1ID property, you can remove it, and it will still work out just fine.