MrteR Ответов: 1

IQueryable<T & gt; результат выполнения бизнес-логики после загрузки сущностей


У меня есть приложение WPF MVVM и универсальная модель данных, которая возвращает IQueryable<t>
Я хочу выполнить некоторую бизнес-логику (например, обновить свойства poco с определенными значениями), когда запрос был выполнен для результирующего набора сущностей. Эта бизнес-логика очень важна, поэтому я не хочу помещать ее везде в коде, где я использую IQuerable. Я надеюсь, что это каким-то образом возможно сделать на уровне Datamodel. Я знаю, что лучше избегать использования IQueryable вне вашей модели данных, но по некоторым конкретным причинам это невозможно.

Идеи у всех?

Заранее спасибо

Что я уже пробовал:

Я гуглил в течение нескольких часов, но не могу найти применимого решения.

1 Ответов

Рейтинг:
1

Andy Lanng

Расширения Linq включают в себя ToArray,ToList и т. д. Все они (включая foreach и т. д.) запускают запрос, преобразующий ваш IQueriable< t> в другие типы данных.

Вы должны построить свой IQueriable внутри вашей модели данных, используя частичные классы. вот пример:

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();
    }
}
}


видите, как я сохраняю то, что требует внимания, как внутреннее? Я могу использовать его в других частичных классах в случае условных соединений и т. д., Но я всегда возвращаю объекты после выполнения запроса.

В этом случае я, возможно, захочу всегда исключать элементы с "ExpiredDate", а не null. Я просто меняю запросы вот так:
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();
    }
}
}


Обратите внимание, как я изменил запрос, чтобы исключить истекший срок действия, но сохранил внутренний базовый запрос "QueryWithExpired". Я сохраню это на случай, если в будущем мне понадобится получить доступ к ним из другого частичного класса.

Это было сделано для того, чтобы вы могли хранить всю свою логику запросов внутри своей модели данных и никогда не выставлять IQueriable за ее пределами.