views:

236

answers:

6

Assuming a basic 3-Tier application (UI-Service-Data Access) with a total abstraction of Data Access layer (SQL, Xml ...)

The UI applications are composed with Datagrids with multi criteria filters, find etc..

So how-to deal with mutli-criteria queries in this architecture without having to create multiple service methods with all possible criteria as parameters...

Note that UI tier doesn't know how the DAL works.

A: 

I use subsonic and pass a collection of where clauses to the service method

ptutt
How do you handle this ? you pass SQL where clauses to the service method ? My UI tier doesn't know how the DAL works, so i can't pass plain SQL where clauses through my service methods.
Yoann. B
You have share the DAL with the client to get this to work. It's not really 'pure' but works really well. You just gotta know that you can't call the CRUD methods from the client.
ptutt
@ptuttNo i can't share the DAL with the client. I think it's not a great architecture design. The client only talk to service layer (business)
Yoann. B
You could split the table definition classes (ie dto's) and where clause classes from the DAL into a separate assembly that could be shared between client and server.
ptutt
@Yoann: i think what ptutt means is that you need to share the model objects (DTOs) with the client. these may or may not be in your DAL project and are certainly not your data access implementation (which i think is this 'not a great architecture design' you're reffering to) so you're ok there.
cottsak
+1  A: 

That is what a DTO is for.

blu
A: 

I'm not sure if this is what you're looking for, but I use the DAL as a factory to create a DAL-aware object, with reasonable public properties and/or methods that encapsulate the various filter criteria.

Ask the DAL to create the object, edit filter criteria as needed, give it back, and let the DAL do it's thing with the object in whatever way it needs to for its given access method.

This, of course, assumes that you don't have a completely open-ended data structure...that you have a known and reasonable sized set of possible filter criteria. If it needs to be flexible to the point where you can pass in arbitary filter criteria for unknown data structures, this probably isn't your solution.

Beska
@BeskaI need a generic and abstract way to handle multi criteria queries. But not specifics methods like this :public IList<MyObject> FindSomething(int filter1, string filter2 ...)But maybe a more flexible way with LINQ Expression like :public IList<T> Find(Expression filters[])I dunno ...
Yoann. B
A: 

You could create an object that holds something like a KeyValuePair for each criteria you want to filter on. Your DAL can then build the where condition from that..

Like this:

class MultiCriteriaFiltering
{
    List<FilterCriteria> Criterias;

    // this method just sits here for simplicity - it should be in your DAL, not the DTO
    string BuildWhereCondition()
    {
        StringBuilder condition = new StringBuilder();
        condition.Append("WHERE (1=1) "
        foreach (FilterCriteria criteria in Criterias)
        {
            condition.Append(" AND ").Append(criteria.FieldName).Append(" = ");
            condition.Append("'").Append(criteria.FilterValue).Append("'");
        }
        return condition.ToString();
    }
}

class FilterCriteria
{
    string FieldName { get; set; }
    object FilterValue  { get; set; }
}

You could quite easily extend on that, e.g. add an "operator" field to the FilterCriteria class, to allow for more filtering options than just exact matches..

andyp
A: 
Jacob O'Reilly
A: 

Check out Rob's Storefront tutorial. It uses a model that is passed up from the DAL, thru the Service layer and even used in the UI layer. This ok, and doesn't break you requirement where the UI can't know how the DAL is implemented. You can easily move your Domain Model onto another VS project in the event you wanted 3rd party apps to access your service layer and not be aware how the DAL works.

This answer has some details about ways to abstract functions of LinqToSql away in higher layers. You might want to do this if, like me, you love the deferred execution features of LinqToSql but you don't want your app to depend on LinqToSql as a data provider.

cottsak