简体   繁体   中英

How to explicitly load mapping tables with Entity Framework?

I have to optimize my Entity Framework queries as the generated SQL is getting more and more complex because of multiple .Include(...) statements.

Instead of using Includes, I started to use explicit loading which is nice, since I have some small tables which are better to be loaded explicitly by the Load method of QueryableExtensions.

However, I cannot find an easy way to explicitly load my mapping tables for many-to-many connected tables - since the mapping table is not mapped to a DbSet...

I use Code First with mappings like this:

 modelBuilder.Entity<SomeEntity>()
             .HasMany(a => a.SomeProperty)
             .WithMany()
             .Map(c =>
             {
                  c.ToTable("MappingTable");
             });

Is there any easy way to explicity load the MappingTable without mapping them?

Now I realized Include statements generate UNIONs when I include multiple (at least 2) fields with many-to-many relationships - it seems to be logical, although at first I didn't see what was going on in the background. The problem with multiple UNIONs is that the query could be quite complex if there are a lot of them.

It turned out that I can "prefetch" the many-to-many connections using the same query filter. If I do the prefetching for every many-to-many connection, this simplifies the query (although it makes multiple roundtrips to the DB server, but it's not a big issue for me).

So to illustrate it with an example - instead of writing something like:

var query = ctx.Employee
               .Include(e => e.ContactAddresses)
               .Include(e => e.Contracts)
               .MyFilter();

query.ToList().Select(e => 
{
    ContactNames = e.ContactAddresses.Select(c => c.DisplayName),
    ContractNames = e.Contracts.Select(c => c.DisplayName)
});

Write something like:

ctx.Employee.Include(e => e.ContactAddresses).MyFilter().ToList();
ctx.Employee.Include(e => e.Contracts).MyFilter().ToList();


var query = ctx.Employee
               .MyFilter();

query.ToList().Select(e => 
{
    ContactNames = e.ContactAddresses.Select(c => c.DisplayName),
    ContractNames = e.Contracts.Select(c => c.DisplayName)
});

Where MyFilter() contains your filtering logic which are part of the queries (Where statements, etc...)

And this solution is also superior to explicitly loading the whole mapping tables (which was my first idea - see the original question), because the mapping tables can be quite big in certain situations.

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