我有一个城市类别,代表其邮政编码。我也有一个Route类,代表两个城市之间的公交路线。因此,我希望在Route类中具有cityFrom和cityTwo属性,都具有City类型-与所涉及的同一类具有多对多关系。
如何首先使用EF Core代码实现这一目标?
谢谢!
更新:
我的模型如下所示:
public class Route
{
public int Id { get; set; }
public City CityFrom { get; set; }
public City CityTo { get; set; }
}
public class City
{
public int Id { get; set; }
public int PostCode { get; set; }
public string Name { get; set; }
}
这能解决我的问题吗?
modelBuilder.Entity<Route>()
.HasOne(f => f.CityFrom)
.WithMany()
.HasForeignKey(f => f.CityFromId);
modelBuilder.Entity<Route>()
.HasOne(f => f.CityTo)
.WithMany()
.HasForeignKey(f => f.CityToId);
还要在Route模型中添加int属性CityFromId和CityToId吗?
答案 0 :(得分:1)
您可以使用Data Annotations
根据您的要求,我们可以引入一个名为CityRoute
的新类,该类代表many-to-many
和City
之间的Route
public class Route
{
public int RouteId { get; set; } // change to make it more specific id
public string CityFrom { get; set; }
public string CityTo { get; set; }
public ICollection<CityRoute> CityRoutes { get; set; }
}
public class City
{
public int CityId { get; set; } // change to make it more specific id
public int PostCode { get; set; }
public string Name { get; set; }
public ICollection<CityRoute> CityRoutes { get; set; }
}
// new class
public class CityRoute
{
public City City { get; set; }
public int CityId { get; set; }
public Route Route { get; set; }
public int RouteId { get; set; }
}
您的DataAnnotations
可能是这样
modelBuilder.Entity<CityRoute>()
.HasKey(cr => new {cr.CityId, cr.RouteId});
希望对您有帮助
答案 1 :(得分:0)
我不会设计这是一个多对多的关系。
每条路线都只有一个由外键FromCityId定义的FromCity。
每条路线都只有一个由外键ToCityId定义的ToCity。
public class Route
{
public int Id { get; set; }
// Every Route has one starting City defined by foreign key:
public int FromCityId { get; set; }
public virtual City FromCity { get; set; }
// Every Route has one termination city, defined by foreign key
public virtual int ToCityId { get; set; }
public virtual City ToCity { get; set; }
...
}
和DbContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Proper name for table of Cities
ModelBuilder.Entity<City>().ToTable("Cities");
// Every Route has one required starting point defined by foreign key
// Several routes may use the same City Id
modelBuilder.Entity<Route>()
.HasRequired(route => route.FromCity)
.WithMany()
.HasForeignKey(route => route.FromCityId)
.WillCascadeOnDelete(false);
// Every Route has one required termination point defined by foreign key
// Several routes may use the same City Id
modelBuilder.Entity<Route>()
.HasRequired(route => route.ToCity)
.WithMany()
.HasForeignKey(route => route.ToCityId)
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
如果您删除一条路线,那么您不希望它们的城市被删除,因为它们可能被其他路线使用:因此,我们不希望级联删除 CascadeOnDelete(false)
答案 2 :(得分:0)
EFCore 3。 需要自己的多对多课程。
我的问题是:人与人的关系(n-> m)
我的解决方案。 创建一个实现多对多关系的关系类。 我为班级中的记录选择了自己的ID。 因此,关系类具有1个PK和2个FK(均为Person类)。
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Relationship> MyRelationships { get; set; }
public List<Relationship> TheirRelationships { get; set; }
}
// MyRelationships用于我添加为关系的人。 //将其添加为我的人的关系。
public class Relationship {
public int RelationshipID { get; set; }
public DateTime Since { get; set; }
//ref to person myrelationships
public int MyID { get; set; }
public Person Me { get; set; }
//ref to person theirrelationships
public int TheirID { get; set; }
public Person They { get; set; }
}
使用添加迁移和更新数据库,我了解到在这种特殊情况下,EFCore无法解析对哪个关系使用哪个FK。 我使用了流畅的API来解决了这个问题。
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//Write Fluent API configurations here
modelBuilder.Entity<Person>()
.HasMany<Relationship>(mr => mr.MyRelationships)
.WithOne(p => p.Me)
.HasForeignKey(m => m.MyID)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Person>()
.HasMany<Relationship>(tr => tr.TheirRelationships)
.WithOne(p => p.They)
.HasForeignKey(t => t.TheirID)
.OnDelete(DeleteBehavior.NoAction);
}
public DbSet<Person> People { get; set; }
public DbSet<Relationship> Relationships { get; set; }
}
现在添加迁移xxx可以使用了:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "People",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
FirstName = table.Column<string>(nullable: true),
MiddleName = table.Column<string>(nullable: true),
LastName = table.Column<string>(nullable: true),
Email = table.Column<string>(nullable: true),
UserID = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_People", x => x.ID);
table.ForeignKey(
name: "FK_People_AspNetUsers_UserID",
column: x => x.UserID,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_People_UserID",
table: "People",
column: "UserID");
migrationBuilder.CreateTable(
name: "Relationships",
columns: table => new
{
RelationshipID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Since = table.Column<DateTime>(nullable: false),
Kind = table.Column<int>(nullable: false),
MyID = table.Column<int>(nullable: false),
TheirID = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Relationships", x => x.RelationshipID);
table.ForeignKey(
name: "FK_Relationships_People_MyID",
column: x => x.MyID,
principalTable: "People",
principalColumn: "ID");
table.ForeignKey(
name: "FK_Relationships_People_TheirID",
column: x => x.TheirID,
principalTable: "People",
principalColumn: "ID");
});
migrationBuilder.CreateIndex(
name: "IX_Relationships_MyID",
table: "Relationships",
column: "MyID");
migrationBuilder.CreateIndex(
name: "IX_Relationships_TheirID",
table: "Relationships",
column: "TheirID");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Relationships");
migrationBuilder.DropTable(
name: "People");
}
}