As I understand in the 3-tier architecture, the presentation layer talks to business logic layer, which talks to data access layer. And, ideally, business layer knows nothing about presentation, and data access layer knows nothing about business layer. I want to write classes to do CRUD database work that are separate from the domain classes. For example, Foo is a domain class in business layer, and I want to write a PersistFoo class that takes Foo objects and CRUDs. My question is (somewhat theoretical?) which layer does PersistFoo go in? Logically, it belongs in the data layer to me. However, PersistFoo depends on Foo (e.g. it reads database and converts data to Foo objects and returns them). So, if PersistFoo is in the data layer, then it depends on the business layer, which violates that lower layers should not depend on higher layers.
There are a couple approaches you can take here, depending on the complexity of your application.
If it's a simple 3 tier application where your domain object map closely (or exactly) to your database table(s), then you can think of your domain object as cross cutting, meaning they can be put in their own assembly and shared across both the business and data access layers. If your application simply wants to do CRUD operations on Foo objects, why add unnecessary abstraction layers. Don't over engineer :) You'll still have the dependencies going down the stack (presentation -> service -> database) and not up.
Another possibility is to do something like I've done at my current job. We have a poorly designed legacy database where the data model is much different than the domain model. Some domain objects are sourced from multiple data objects. So what we do is we have both domain and data objects, and the business layer is the only layer that depends on both. Presentation layer depends on the domain objects, and the database layer depends on the data objects. There are translation services in the business layer.