英文:
EF Core Many To Many with owning relationship that has one
问题
Given the provided information, here's the translation of the code section:
internal class Character
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; } = string.Empty;
public virtual ICollection<Character_Abilities> Character_Abilities { get; set; } = new List<Character_Abilities>();
}
internal class Character_Abilities
{
public virtual Guid Id { get; set; }
public virtual Guid CharacterId { get; set; } = default!;
public virtual int AbilityId { get; set; } = default!;
}
internal class Ability
{
public virtual int Id { get; set; }
public virtual string Name { get; set; } = string.Empty;
}
With a Fluent Config like
public DbSet<Character> Characters { get; set; } = default!;
public DbSet<Ability> Abilities { get; set; } = default!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Character>(character =>
{
character.OwnsMany(
t => t.AbilitiesLookup,
char_abil =>
{
char_abil.HasOne<Ability>();
});
});
}
Please note that the code provided here is based on the C# and Entity Framework. It defines classes for Character
, Character_Abilities
, and Ability
, and sets up their relationships using Entity Framework's Fluent API.
英文:
Given the following three tables what is the best way to set up the classes on the C# side along with the needed fluent configuration?
Character | Character_Abilities | Ability |
---|---|---|
Id | Id | Id |
Name | CharacterId | Name |
Abilities | AbilityId |
For the sake of matching my need, I will never need to get the characters by ability. Only character to abilities.
In my thinking I need to have three classes (only cause of the id on the lookup table)
abilities can be added by anyone, but no one owns them. When a character is deleted it should clean up the references in the lookup table but not delete any of it's referenced abilities. abilities can be used by any character.
I would think I need
internal class Character
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; } = string.Empty;
public virtual ICollection<Character_Abilities> Character_Abilities{ get; set; } = new List<Character_Abilities>();
}
internal class Character_Abilities
{
public virtual Guid Id { get; set; }
public virtual Guid CharacterId {get;set;) = default!;
public virtual int AbilityId { get; set; } = default!;
}
internal class Ability
{
public virtual int Id { get; set; }
public virtual string Name { get; set; } = string.Empty;
}
With a Fluent Config like
public DbSet<Character> Characters { get; set; } = default!;
public DbSet<Ability> Abilities { get; set; } = default!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Character>(character=>
{
character.OwnsMany(
t => t.AbilitiesLookup,
char_abil=>
{
char_abil.HasOne<Ability>();
});
});
it makes sense to me as an owns many and a has one relationship as I only want to go one way. but how do I specify the entity for the middle table in the owning side? maybe I'm overthinking the relationship table. What am I missing?
In a perfect world my Character class should contain a list of Abilities; no reference to the lookup table.
答案1
得分: 1
请注意,对于连接表,实际上不需要使用替代id,如果您不打算将其公开为单独的表(即 public DbSet<CharacterAbility> Characters => Set<CharacterAbility>()
),您可以仅依赖约定来生成“完全定义关系”的表:
public class Character
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; } = string.Empty;
public virtual ICollection<Ability> Abilities { get; set; } = new List<Ability>();
}
public class Ability
{
public virtual int Id { get to; set; }
public virtual string Name { get; set; } = string.Empty;
public virtual ICollection<Character> Characters { get; set; } = new List<Character>();
}
如果您想指定表名称,那么您可以使用流畅的API来配置它:
modelBuilder
.Entity<Character>()
.HasMany(p => p.Abilities)
.WithMany(p => p.Character)
.UsingEntity(j => j.ToTable("Character_Abilities"));
英文:
Note that surrogate id is not actually required for join table and if you are not going to expose it as a separate table (i.e. public DbSet<CharacterAbility> Characters => Set<CharacterAbility>()
) you can just rely on conventions to generate the table for "fully defined relationship":
public class Character
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; } = string.Empty;
public virtual ICollection<Ability> Abilities { get; set; } = new List<Ability>();
}
public class Ability
{
public virtual int Id { get; set; }
public virtual string Name { get; set; } = string.Empty;
public virtual ICollection<Character> Characters { get; set; } = new List<Character>();
}
If you want to specify the table name then you can use the fluent API to configure it:
modelBuilder
.Entity<Character>()
.HasMany(p => p.Abilities)
.WithMany(p => p.Character)
.UsingEntity(j => j.ToTable("Character_Abilities"));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论