我有两个实体-团队和游戏。一个团队可以有很多场比赛(一对多)。
所以看起来像这样:
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
这很好用,但我想通过将游戏分为两类(主场和客场游戏)来使其更加精致。但是,这将在两个实体之间引入另一个关系,我不确定如何定义它。
我想会是这样吗?
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Game> Games { get; set; }
}
public class Game
{
public int Id { get; set; }
public DateTime Date { get; set; }
public int TeamId { get; set; }
public Team Team { get; set; }
}
这样做会混淆实体框架,并且无法决定如何解决关系。
有什么想法吗?
答案 0 :(得分:3)
基于Relationships - EF Core | Microsoft Docs,您可以使用数据注释
数据注释
有两个数据注释可用于配置 关系,[ForeignKey]和[InverseProperty]。
[ForeignKey]
您可以使用数据注释来配置 属性应用作给定的外键属性 关系。通常在外键属性为 未被惯例发现。
[InverseProperty]
您可以使用数据注释来配置 从属实体和主体实体上的导航属性配对。 通常在导航对多于一对时完成 两种实体类型之间的属性。
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty("HomeTeam")]
public ICollection<Game> HomeGames { get; set; }
[InverseProperty("AwayTeam")]
public ICollection<Game> AwayGames { get; set; }
}
public class Game
{
public int Id { get; set; }
public DateTime Date { get; set; }
public int HomeTeamId { get; set; }
[ForeignKey("HomeTeamId")]
public Team HomeTeam { get; set; }
public int AwayTeamId{ get; set; }
[ForeignKey("AwayTeamId")]
public virtual Team AwayTeam { get; set; }
}
如果使用db.Database.Migrate(),则会出现错误提示
System.Data.SqlClient.SqlException:'引入外键 表“游戏”上的约束“ FK_Games_Teams_HomeTeamId”可能会导致 循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。不能 创建约束或索引。查看先前的错误
您可以将HomeTeamId AwayTeamId int?设置为可空
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty("HomeTeam")]
public ICollection<Game> HomeGames { get; set; }
[InverseProperty("AwayTeam")]
public ICollection<Game> AwayGames { get; set; }
}
public class Game
{
public int Id { get; set; }
public DateTime Date { get; set; }
public int? HomeTeamId { get; set; }
[ForeignKey("HomeTeamId")]
public Team HomeTeam { get; set; }
public int? AwayTeamId{ get; set; }
[ForeignKey("AwayTeamId")]
public virtual Team AwayTeam { get; set; }
}
或参见Cascade Delete - EF Core | Microsoft Docs
这里是我测试和工作的完整代码(先
对于代码,请先使用 int?
对于Program.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace stackoverflow54196199
{
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty("HomeTeam")]
public ICollection<Game> HomeGames { get; set; }
[InverseProperty("AwayTeam")]
public ICollection<Game> AwayGames { get; set; }
}
public class Game
{
public int Id { get; set; }
public DateTime Date { get; set; }
public int HomeTeamId { get; set; }
[ForeignKey("HomeTeamId")]
public Team HomeTeam { get; set; }
public int AwayTeamId { get; set; }
[ForeignKey("AwayTeamId")]
public Team AwayTeam { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Game> Games { get; set; }
public DbSet<Team> Teams { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=.;Integrated Security=true;Initial Catalog=stackoverflow54196199;Persist Security Info=False;");
}
}
class Program
{
static void Main(string[] args)
{
var db = new MyContext();
foreach (var game in db.Games.Include(i => i.AwayTeam).Include(i => i.HomeTeam))
{
Console.WriteLine(game.HomeTeam.Name);
Console.WriteLine(game.AwayTeam.Name);
}
Console.ReadLine();
}
}
}
对于stackoverflow54196199.csproj
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.0" />
</ItemGroup>
答案 1 :(得分:2)
您必须告诉Entity Framework一个关联中涉及两个实体中的哪些属性。在流利的Mapping API中,这是:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Team>().HasMany(t => t.HomeGames)
.WithOne(g => g.HomeTeam)
.HasForeignKey(g => g.HomeTeamId);
modelBuilder.Entity<Team>().HasMany(t => t.AwayGames)
.WithOne(g => g.AwayTeam)
.HasForeignKey(g => g.AwayTeamId).OnDelete(DeleteBehavior.Restrict);
}
您必须使用fluent API,因为默认情况下,EF将尝试使用级联删除创建两个外键。由于臭名昭著的“多个级联路径”限制,SQL Server不允许这样做。密钥之一不应该是级联的,只能由流利的API配置。