EF核心许多同级

时间:2018-06-28 15:32:42

标签: asp.net-core .net-core ef-code-first ef-core-2.0

我有一个城市类别,代表其邮政编码。我也有一个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吗?

3 个答案:

答案 0 :(得分:1)

您可以使用Data Annotations

在ASP.NET Core中实现多对多关系。

根据您的要求,我们可以引入一个名为CityRoute的新类,该类代表many-to-manyCity之间的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");
    }
}