Ming Tong
Ming Tong

Reputation: 119

How to define DbSet for auto generated many to many table in EF Core 5?

https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-5.0/whatsnew#many-to-many

EF Core 5 has refined the many to many relationship, we don't need to define a Entity for the "relation table", EF Core 5 will internally automatically generated the table.

Then, how can I define the DbSet for referencing to do CRUD?

e.g.

class T1
{
    public string id1{get;set;}
    public virtual ICollection<T2> T2{get;set;}
}
class T2
{
    public string id2{get;set;}
    public virtual ICollection<T1> T1{get;set;}
}

public DbSet<T1> t1{ get; set; }
public DbSet<T2> t2{ get; set; }

So no

public DbSet<T1T2> t1t2{ get; set; }

While I what to add a record to T1T2, how to get the reference of the Table T1T2? Or do I have any other way to do so?

Upvotes: 3

Views: 1147

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205589

By default EF Core uses the so called shared property bag entity type for join entity. In simple words, it is Dictionary<string, object> type with unique name, having named "indexer" properties.

It is possible to define/access DbSet for it as soon as you know the name. You do that by using the new Set method overload with name argument:

public DbSet<Dictionary<string, object>> t1t2 => Set<Dictionary<string, object>>("T1T2");

Then you can query or do any operation as with regular typed entity, but dealing with "magic" string property names and types, for instance

context.t1t2.Add(new Dictionary<string, object> { ["T1id1"] = some_id1, ["T2id2"] = some_id2 });

etc.

Shortly, it's possible to work explicitly with the join entity, but it's type unsafe and error prone (similar to working with shadow properties), and more importantly, normally is not needed. Because the operations on join entity (links) - basically add and remove, are normally implemented through manipulating the collection navigation property of one of the entities. For instance, do add link between two existing entities as above, you do something like this

var t1 = context.t1.Find(some_id1);
var t2 = context.t2.Find(some_id2);

and then either

t1.T2.Add(t2);

or

t2.T1.Add(t1);

would do the desired operation (make sure you initialize collection navigation properties of your entities to avoid null reference exceptions, but this is no different than for normal one-to-many relationships).

Upvotes: 2

Related Questions