---------------- describing why this is not a duplicate -------------
EDIT: This is different than the question marked as a duplicate because I am not trying to re-query the list that is returned (and further refine it). E.G. If I change the ClientProviderAccountRep.GetByProviderID
method from a .Where
to a .First()
, I would still expect the following to be optimized with an EXISTS:
If I change the GetByProviderID to this:
public ClientProviderAccount GetByProviderID(Guid providerID)
{
return Db.ClientProviderAccounts.First(cpa => cpa.IsActive && cpa.ProviderID == providerID);
}
Then use that method here:
var clientProviderAccount = ClientProviderAccountRep.GetByProviderID(providerId);
var schedulesExist = clientProvider.Schedules.Any();
Our application uses entity framework 6.1. The entity can have a large collection of children (schedules). We have a method that is transforming the EF entity into a viewmodel entity. For the purpose of the ViewModel, it does not need all the schedules. It just needs to know if one exists. I expected using .Any()
would not get the query and create the whole list of schedules.
var lst = ClientProviderAccountRep.GetByProviderID(providerID).Select(x => new ClientProviderAccountVM
{
ClientProviderAccountID = x.ClientProviderAccountID,
ClientID = x.ClientID,
ClientName = x.Client.Name,
ProviderID = x.ProviderID,
ProviderName = x.Provider.Name,
Name = x.Name,
LoginID = x.LoginID,
Password = x.Password,
StartRecordNumber = x.StartRecordNumber,
IsActive = x.IsActive,
SchedulesExist = x.Schedules.Any(s => s.IsActive == true)
})
The problem line is:
SchedulesExist = x.Schedules.Any(s => s.IsActive == true)
I would have expected a really quick EXISTS call, but it is getting all the schedule objects first.
Things I have tried:
foreach
instead of the.GetByProviderID(providerID).Select(x.
then creating ViewModel with the object initializer syntax.- in a loop, creating a new ViewModel and setting each property explicitly.
I am pretty sure I tried other permutations, but have not been successful.
here is the generated DbContext:
public partial class AppLogDb : DbContext
{
public AppLogDb()
: base("name=AppLogDb")
{
this.Configuration.LazyLoadingEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<ApplicationLog> ApplicationLogs { get; set; }
public virtual DbSet<AuditLog> AuditLogs { get; set; }
public virtual DbSet<LogDetail> LogDetails { get; set; }
public virtual DbSet<LoginLog> LoginLogs { get; set; }
}
Here is the GetByProviderID method. The Db is the database context. I know there is a too list, but I don' think that is it because it is still lazy loading the schedules after returning from this method. The ToLis(), just realizes the top parent object (I think).
public IEnumerable<ClientProviderAccount> GetByProviderID(Guid providerID)
{
var clientProviderAccount = Db.ClientProviderAccounts
.Where(cpa => cpa.IsActive && cpa.ProviderID == providerID)
.ToList();
return clientProviderAccount.OrderBy(cpa => cpa.Name);