EF Core具有一个拥有一对多关系的多对多关系

huangapple go评论57阅读模式
英文:

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&lt;Character_Abilities&gt; Character_Abilities{ get; set; } = new List&lt;Character_Abilities&gt;();
}

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&lt;Character&gt; Characters { get; set; } = default!;

public DbSet&lt;Ability&gt; Abilities { get; set; } = default!;


protected override void OnModelCreating(ModelBuilder modelBuilder)
		{
            modelBuilder.Entity&lt;Character&gt;(character=&gt;
			{
			character.OwnsMany(
				t =&gt; t.AbilitiesLookup,
				char_abil=&gt;
				{
					char_abil.HasOne&lt;Ability&gt;();
				});
			});

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&lt;CharacterAbility&gt; Characters =&gt; Set&lt;CharacterAbility&gt;() ),您可以仅依赖约定来生成“完全定义关系”的表:

public class Character
{
    public virtual Guid Id { get; set; }

    public virtual string Name { get; set; } = string.Empty;

    public virtual ICollection&lt;Ability&gt; Abilities { get; set; } = new List&lt;Ability&gt;();
}


public class Ability
{
    public virtual int Id { get to; set; }

    public virtual string Name { get; set; } = string.Empty;

    public virtual ICollection&lt;Character&gt; Characters { get; set; } = new List&lt;Character&gt;();
}

如果您想指定表名称,那么您可以使用流畅的API来配置它

modelBuilder
    .Entity&lt;Character&gt;()
    .HasMany(p =&gt; p.Abilities)
    .WithMany(p =&gt; p.Character)
    .UsingEntity(j =&gt; j.ToTable(&quot;Character_Abilities&quot;));
英文:

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&lt;CharacterAbility&gt; Characters =&gt; Set&lt;CharacterAbility&gt;()) 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&lt;Ability&gt; Abilities { get; set; } = new List&lt;Ability&gt;();
}


public class Ability
{
    public virtual int Id { get; set; }

    public virtual string Name { get; set; } = string.Empty;

    public virtual ICollection&lt;Character&gt; Characters { get; set; } = new List&lt;Character&gt;();
}

If you want to specify the table name then you can use the fluent API to configure it:

modelBuilder
    .Entity&lt;Character&gt;()
    .HasMany(p =&gt; p.Abilities)
    .WithMany(p =&gt; p.Character)
    .UsingEntity(j =&gt; j.ToTable(&quot;Character_Abilities&quot;));

huangapple
  • 本文由 发表于 2023年3月23日 09:51:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75818663.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定