Click here to Skip to main content
15,891,136 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have an WPF MVVM application and a generic Datamodel which returns an IQueryable<t>
I want to execute some business logic (e.g. update poco properties with specific values) when the query has been executed on the result set of Entities. This business logic is important so I don't want to put this everywhere in code where I use the IQuerable. I'll hope it's somehow possible to do this at Datamodel level. I know it's better to avoid using IQueryable outside of your Datamodel but for some specific reasons it's impossible.

Ideas everyone?

Thanks in advance

What I have tried:

I have Googled for several hours but I can't find an applicable solution.
Posted
Updated 16-Oct-17 3:12am

1 solution

Linq extensions includes ToArray, ToList etc. All of these (including foreach etc...) run the query converting your IQueriable<t> into other data types.

You should build your IQueriable within your datamodel using partial classes. here is an example:

C#
namespace myContextNamespace
{
public partial class Item
{
    internal IQueriable<Item> Query(ContextDB db = null)
    {
        if(db==null)
            db = new ContextDB();
        return db.Items;
    }
    internal IQueriable<Item> QueryById(int id, ContextDB db = null)
    {
        if(db==null)
            db = new ContextDB();
        return Query(db).Where(i=>i.Id == id);
    }
    public List<Item> SelectAll(ContextDB db = null)
    {
        if(db==null)
            db = new ContextDB();
        return Query(db).ToList();
    }
    public Item SelectById(int id, ContextDB db = null)
    {
        if(db==null)
            db = new ContextDB();
        return QueryById(id,db).SingleOrDefault();
    }
}
}


see how I keep the queriable as internal? I can use it in other partial classes in the case of conditional joins etc., but I always return the objects after executing the query.

In this case I may want to always exclude items with "ExpiredDate" not null. I simply change the queries like so:
C#
namespace myContextNamespace
{
public partial class Item
{
    internal IQueriable<Item> Query(ContextDB db = null)
    {
        if(db==null)
            db = new ContextDB();
        return QueryWithExpired(db).Where(i=>!i.ExpiredDate.HasValue);
    }
    internal IQueriable<Item> QueryWithExpired(ContextDB db = null)
    {
        if(db==null)
            db = new ContextDB();
        return db.Items;
    }
    internal IQueriable<Item> QueryById(int id, ContextDB db = null)
    {
        if(db==null)
            db = new ContextDB();
        return Query(db).Where(i=>i.Id == id);
    }
    public List<Item> SelectAll(ContextDB db = null)
    {
        if(db==null)
            db = new ContextDB();
        return Query(db).ToList();
    }
    public Item SelectById(int id, ContextDB db = null)
    {
        if(db==null)
            db = new ContextDB();
        return QueryById(id,db).SingleOrDefault();
    }
}
}


Note how I have changed Query to exclude expired but kept an internal base query "QueryWithExpired". I will keep this in case I need to access them from another partial class in the future.

This was you can keep all your query logic within your datamodel and never expose an IQueriable outside of it.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900