Ho due entità - Squadra e Gioco . Una squadra può avere molti giochi (uno a molti).
Quindi sarebbe simile a questo:
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; }
}
Funziona bene, ma voglio renderlo un po 'più raffinato suddividendo i giochi in due categorie: i giochi Casa e Fuori. Ciò introdurrà comunque un'altra relazione tra le due entità e non sono sicuro di come definirlo.
Immagino che sarà qualcosa del genere?
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Game> HomeGames { get; set; }
public ICollection<Game> AwayGames { get; set; }
}
public class Game
{
public int Id { get; set; }
public DateTime Date { get; set; }
public int HomeTeamId { get; set; }
public Team HomeTeam { get; set; }
public int AwayTeamId{ get; set; }
public Team AwayTeam { get; set; }
}
Questo confonde Entity Framework e non può decidere come risolvere le relazioni.
Qualche idea?
Devi dire a Entity Framework quali proprietà in entrambe le entità sono coinvolte in un'associazione. Nell'API di mappatura fluente questo è:
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);
}
Devi usare l'API fluente perché, per impostazione predefinita, EF proverà a creare due chiavi esterne con eliminazione a cascata. SQL Server non lo consentirà a causa della sua famigerata limitazione "percorsi a cascata multipli". Una delle chiavi non dovrebbe essere a cascata, che può essere configurata solo dall'API fluente.
Base sulle relazioni - EF core | Microsoft Docs è possibile utilizzare le annotazioni di dati
Annotazioni di dati
Esistono due annotazioni di dati che possono essere utilizzate per configurare le relazioni, [ForeignKey] e [InverseProperty].
[ForeignKey]
È possibile utilizzare Annotazioni dati per configurare quale proprietà deve essere utilizzata come proprietà della chiave esterna per una determinata relazione. Questo in genere viene eseguito quando la proprietà della chiave esterna non viene rilevata per convenzione.
[InverseProperty]
È possibile utilizzare le Annotazioni dei dati per configurare il modo in cui le proprietà di navigazione sulle entità dipendenti e principali si accoppiano. Questo viene in genere fatto quando c'è più di una coppia di proprietà di navigazione tra due tipi di entità.
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; }
}
se usi db.Database.Migrate () otterrai erro
System.Data.SqlClient.SqlException: 'L'introduzione del vincolo FOREIGN KEY' FK_Games_Teams_HomeTeamId 'sulla tabella' Giochi 'potrebbe causare cicli o più percorsi a cascata. Specificare ON DELETE NO ACTION o ON UPDATE NO ACTION o modificare altri vincoli FOREIGN KEY. Impossibile creare vincoli o indici. Vedi errori precedenti
puoi rendere HomeTeamId AwayTeamId int? annullabile
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; }
}
oppure vedi Cascade Delete - EF Core | Microsoft Docs
qui il codice completo ho testato e funzionante ( db prima non prima il codice )
per il primo utilizzo del codice int?
per 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();
}
}
}
per 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>