Interesting that although you tagged it entity-framework, most answers don't come up with the simplifications that entity-framework offers you.
There is a one-to-many relationship between Owners and Pets. Every Owner has zero or more Pets, every Pet belongs to exactly one Owner.
If you have configured your entity framework classes correctly for a one-to-many relationship, they will be like:
class Owner
{
public int Id {get; set;}
// every Owner has zero or more Pets:
public virtual ICollection<Pet> Pets {get; set;}
... // other properties
}
class Pet
{
public int Id {get; set;}
// every Pet belongs to exactly one Owner, using foreign key:
public int OwnerId {get; set;}
public Owner Owner {get; set;}
}
class MyDbConnection : DbConnection
{
public DbSet<Owner> Owners {get; set;}
public DbSet<Pet> Pets {get; set;}
}
This is enough for entity framework to recognize that you designed the one-to-many relationship. Whenever needed, entity framework will do the correct join for you.
I need to return all owners who have only Active pets or no pets.
This is the same collections as:
I need to return all owners who don't have Inactive pets
(note to self: Owners without Pets, surely don't have Inactive Pets!)
If you've set up the classes correctly, the queries will be much more readable. You can think of collections, instead of tables that are related towards each other using IDs
using (var dbConnection = new MyDbConnection())
{
var requestedOwners = dbConnection.Owners // Give me all Owners
.Where(owner => !owner.Pets.Any() // that have no Pets at all
|| owner.Pets.All(pet => pet.Status == Active)); // or have only active Pets
}
Entity Framework will recognize that this needs a join and will translate this into the correct inner joins for you.
The second query is even simpler, and probably faster because you can continue to the next Owner as soon as an Inactive Pet is found
var ownersWithoutInactivePets = dbContext.Owners // give me all Owners
.Where(owner => !owner.Pets // that don't have
.Any(pet => pet.Status == Inactive); // any inactive Pets
Again, entity framework will do the join for you