简体   繁体   中英

Entity Framework map one to many with an intermediate table without a class for that table

I have

Issue
{
    //Id, etc
    public List<CloudFile> Files { get; set; }
}

and since CloudFile can be used by other classes, the cleanest solution seems to create an intermediate table called IssueFile . The thing is I have no use for such a class in my code... so how do I map between Issue and CloudFile without creating such an intermediate class. Or is this even possible? I know that there are similar questions ( One to Many mapping with an intermediate table ) but they create this intermediate but, hopefully, unnecessary class.

The only time there is no getting out of an intermediate table is for a many-to-many mapping. In your case, you're dealing with a many-to-optional or many-to-required. Now you have two options:

1) Foreign Key association: for this you will need to define your foreign key in your CloudFile class. This has some advantages, because you can update relationships by changing foreign key value and you can add new entities without needing the dependant entity by using dummy foreign key values. Overall it's just easier to work with.

modelBuilder.Entity<Issue>()
  .HasMany(i => i.CloudFile)
  .WithRequired(i => i.Issue)
  .HasForeignKey(i => i.Id);

2) Independant association: no foreign key on your model (it does use the key internally of course) and the relationship has it's own state tracked.

modelBuilder.Entity<Issue>()
  .HasMany(i => i.CloudFile)
  .WithRequired(i => i.Issue)
  .Map(i => i.MapKey("Id"));

What you want is Table-per-Type (TPT) inheritance. CloudFile would be your base class and the derived types would represent the relationship to the owning entities ( Issue , Order , etc.):

[Table( "CloudFile" )]
public class CloudFile
{
    public int Id { get; set; }
}

[Table( "IssueCloudFile" )]
public class IssueCloudFile : CloudFile
{
}

public class Issue
{
    public int Id { get; set; }
    public List<IssueCloudFile> Files { get; set; }
}

Or via Fluent API:

modelBulider.Entity<CloudFile>().ToTable( "CloudFile" );
modelBuilder.Entity<IssueCloudFile>().ToTable( "IssueCloudFile" );

If you use DbSet<CloudFile> only without DbSet s for a derived type of CloudFile , use .OfType<T>() to get only those types:

var issueCloudFiles = db.CloudFiles.OfType<IssueCloudFile>();
// or through the referencing entities themselves
issueCloudFiles = db.Issues.SelectMany( i => i.Files );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM