2013-09-09 3 views
9

Для моих моделей у меня есть атрибут active для всех из них, и я хочу отфильтровать все неактивные, если модель не была отображена администрацией Каков наилучший способ сделать это, что в настоящее время я использую следующиесоздание глобального фильтра для фреймворка сущности

в моей базовой модели класса я этот метод, который фильтрует коллекции

public virtual IQueryable<T> GlobalDefaultScope<T>(IQueryable<T> c) where T : CModel<T> 
{ 
    if (settings.is_admin) 
    { 
     c = c.Where(m => m.active); 
    } 
    return c; 
} 

и на моей модели для каждого отношения я сделал следующий метод

DbSet<T> set ... 
var X = set.Where(some filter); 
var list = globalDefaultScope(X).ToList(); 
return list; 

И теперь у меня возникают серьезные проблемы, когда я хочу с нетерпением загрузить некоторые подзаголовки с помощью include("Xmodel.Ymodel"). Я назвал globalDefaultScope в методе get для этой коллекции, которая фильтрует коллекцию, но она продолжает бросать это исключение, когда некоторые элементы в коллекции неактивный

System.InvalidOperationException: операция не удалась: отношения не могут быть изменены, потому что один или более из внешних ключей свойств не является обнуляемым.

Как я могу исправить это или как я могу сделать этот фильтр более элегантным способом, потому что я действительно не очень доволен тем, как я его реализовал.

пожалуйста, обратитесь к любой пропавшей информации или кодовых блоков или каких-либо деталей

Update:

Я также нашел эту link, но этот способ не работает с нетерпением загруженных записей (include())

Обновление2:

это пример того, как я использовать, включают и порога е ошибка происходит

In My Model

public IQueryable<Dish> getSomeRelation(bool eagerly_load_sub_relation1, bool eagerly_load_sub_relation2) 
     { 
      var query = getQuery(...); 
      //getQuery => query = db.Entry(obj).Collection(collection).Query() 
      //GlobalDefaultScope(query) 
      if (eagerly_load_sub_relation1){ 
       query = query.Include(m => m.sub_relation1); 
      } 
      if (eagerly_load_sub_relation2){ 
       query = query.Include("sub_relation2.sub_relation_of_sub_relation2"); 
      } 
      return query; 
     } 

в то время как я не мог фильтровать отношения в включаемые я сделал следующее:

private ICollection<SubRelation1> _sub_relation1 {get; set;} 
public ICollection<SubRelation1> sub_relation1 { 
get 
{ 
    //something like: 
    return GlobalDefaultScope(_sub_relation1).ToList(); 
} 
set;} 

в то время как мы фильтруем результаты в sub_relation1 , когда я делаю db.SaveChanges(), указанная ошибка возникает.

+0

Если вы включаемые() без применения фильтра он работает, то есть ли ошибка уходит. Можете ли вы показать код того, как применяется приложение. –

+0

@TommyGrovnes Вопрос обновлен, спасибо. – Hilmi

+0

@ Хильми также можете указать таблицы базы данных. (** Что я чувствую, так это то, что для вашего первого корабля отношения вы не получаете значения, поскольку для этого не может быть никаких данных, и вы пытаетесь получить второе отношение null **) – hajirazin

ответ

5

Вы можете создать методы расширения, как

public static IQueryable<T> Where<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate) 
{ 
    source = source.Where("isActive == true"); // From System.linq.Dynamic Library 
    source = Queryable.Where<T>(source, predicate); 
    return source; 
} 

и использовать их как

var user = db.UserProfiles.Include("webpages_Roles").Where(u => u.UserId < 30); 

Это должно работать, пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Примечание: Пожалуйста, добавьте пакет Nuget для System.Linq.Динамические иметь динамический Linq Библиотека

Update 1:

Я включил IsActive в webpages_Roles и UsreProfile таблицы простого членства, а также включен один приоритетную роль более таблицы, которая относится к webpages_Roles, для удобного использования I изменили отношение всех отношений к одному ко многим (от многих к многим). теперь, если я использую код, похожий на ваш, метод расширения дает ошибку, когда есть пользователь, для которого нет ролей.

Если я даю роли каждому пользователю, и у меня есть приоритет для каждой роли, это не даст ошибки.

Пожалуйста, дайте мне знать, если вам по-прежнему нужна дополнительная информация.

Update 2

Вы можете создать один метод расширения как

public static IQueryable<T> WhereActive<T>(this IQueryable<T> source) 
     { 
      return source.Where("isActive == true"); // From System.linq.Dynamic Library 
     } 

и вызывать другие методы, как

var user = db.UserProfiles.Include("webpages_Roles").WhereActive().Where(u => u.UserId < 30); 

или

var user = db.UserProfiles.Include("webpages_Roles").WhereActive().FirstOrDefault(u => u.UserId < 30); 

Пожалуйста, дайте мне знать, если вам по-прежнему нужна какая-либо другая информация.

+0

Сэр, это будет ошибкой использовать этот способ, потому что вы переопределили функцию 'Where', а в моем коде я использую' Где First FirstOrDefault ... 'и многие другие, мне придется перебирать их и переопределять их все, Если я пропустил понимание, пожалуйста, скажите мне, спасибо alot sir – Hilmi

+0

@Hilmi Я бы обновил свой ответ – hajirazin

+0

Спасибо большое, ваш путь хорош, но мне нужно идти по всему сайту и называть метод 'WhereActive', я просто подожду, чтобы найти более централизованный самоуправляемый способ сделать это, если я ничего не нашел (и, кажется, я не буду) i'l Я выбираю и отмечаю ваш ответ как выбранный.Еще раз спасибо – Hilmi

2

Вы можете сделать это следующим образом:

  1. В OnModelCreating добавить IsDeleted дискриминатор для каждого объекта, который может быть мягким удален
  2. Override SaveChanges и найти все записи, которые будут удалены
  3. Run SQL на эти записи для установки дискриминатора IsDeleted затем устанавливают свое состояние на «отсоединенный»
  4. Измените любые уникальные индексы, чтобы игнорировать любые удаленные записи.

Вы можете найти рабочий код на этот ответ: How to soft delete using Entity Framework Code First

+0

Я думаю, именно то, что я искал точно! , но пока он не работает с предварительно сгенерированными видами, я буду искать решение, THANKS alot sir – Hilmi

+0

Как вы можете сделать то же самое с использованием базы данных или почему это невозможно? – xr280xr

Смежные вопросы