2013-06-05 3 views
1

У меня есть User, который присваивается Client. Когда вытаскиваете объект User, я получаю объект Client как часть его. Просто.Entity Framework не всегда включает дочерние объекты

Это работает как следует при входе в систему. Объект User имеет Client, вне зависимости от того, с кем я вхожу.

Однако, используя тот же метод, точный получить User как при входе в систему, чтобы изменить его через меню администратора, то Client иногда null.

Я говорю иногда:

1) В Firefox - При попытке просмотра сведений о большинства, но не все пользователи (и я сам), то Client прилагается к User будет null. Только пара Users будет доступна для просмотра из-за фактически существующего Client.

2) В Chrome - все пользователи (ЗА ИСКЛЮЧЕНИЕМ себя) видны. Только при попытке просмотра моего собственного пользователя Client будет null.

Я не понимаю; Оба браузера просто будет тот же URL,, т.е. /Users/EditGet/28 и даже с использованием двух различных методов (GetById и GetByUserName) он обеспечивает те же результаты - хотя по общему признанию, как сделать использование базы Получить функции:

Edit: BaseService класс вместе а над изменениями.

internal CustomContext context; 
internal DbSet<TEntity> dbSet; 

public BaseService(CustomContext context) 
{ 
    this.context = context; 
    this.dbSet = context.Set<TEntity>(); 
} 

public virtual IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null, 
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
    string includeProperties = "") 
{ 
    IQueryable<TEntity> query = dbSet.Where(e => !e.Deleted); 

    if (filter != null) 
    { 
     query = query.Where(filter); 
    } 

    foreach (var includeProperty in includeProperties.Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries)) 
    { 
     query = query.Include(includeProperty); 
    } 

    return orderBy != null ? orderBy(query).ToList() : query.ToList(); 
} 

Я не уверен, почему выбор браузера должен повлиять на результаты внутреннего запроса вообще. Разумеется, он должен вернуть Client с User независимо от того, какой браузер я использую.

Я предполагаю, что, возможно, основной недостаток с базой Получить метод, но это не объясняет поведение, что я вижу ...

Если кто-то может пролить свет на это, я был бы очень признателен ,

Edit 2: CustomContext:

public class CustomContext : DbContext, ICustomContext 
{ 
    public IDbSet<User> Users { get; set; } 
    public IDbSet<Client> Clients { get; set; } 
} 
+2

Учитывая, что весь этот код работает на сервере, я сомневаюсь, что это зависит от браузера, но это так, как вы заметили, поэтому может быть, что 'includeProperties' является параметром, переданным на одну из страниц mvc и является неправильно отформатирован, чтобы сплит не работал? Поместите точку прерывания на строку запроса 'query = query.Include (includeProperty);' и посмотрите, все ли она удалена –

+0

@QuintonBernhardt: каждый раз это делает каждый раз. Нет проблем с использованием разделения запятой, он правильно попадает в нее для каждого включенного свойства. Даже SQL, сгенерированный EF, является правильным (с использованием SQL Profiler), и выполнение запроса возвращает все, что нужно, но «Клиент» просто не создается и не связан. – Krenom

+0

Почему переменный запрос типа 'IQueryable 'вместо ожидаемого' DbQuery '? IQueryable не имеет метода 'Include', поэтому я не вижу, как это не дает компиляции в строке .Include –

ответ

0

Кажется, что проблема связана с тем, как мы храним в настоящее время зарегистрированный User.

При попытке извлечь другой объект из этого же объекта User он затем не работает и вытаскивает Client.

Все еще не совсем уверен, почему это так. У меня было несколько намеков на то, что это связано с Object State Manager и отслеживанием нескольких объектов, хотя в настоящее время зарегистрированный объект User фактически не вытащил из базы данных ...

Однако проблема устранена , делает для простой проверки, чтобы вытащить User так же, как в настоящее время вошедший в систему User, и если проблема не существует (Client - null), то вытащите Client и прикрепите ее к объекту User.

private User GetUser(long id) 
{ 
    var user = Services.UserService.GetById(id); 
    if (user.Client == null && CurrentUser.Id == user.Id) 
     user.Client = Services.ClientService.GetByClient(CurrentUser.Client); 

    return user; 
} 

Сырая и далеко от достойного ответа относительно того, как правильно работать с этой проблемой, но она работает, и все User s полностью редактируемые еще раз.

0

Вы также можете изменить из разделенных запятыми список включает в себя - которые могут быть склонны к форматированию ошибок; вы можете изменить его Param или массив, как, например:

 public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, 
                Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
                params string[] includeProperties) { 

      var query = ((DbQuery<TEntity>)dbset); 

      query = includeProperties.Aggregate(query, (q, s) => q.Include(s)); 

      query = query.Where(e => !e.IsDeleted); 


      if (filter != null) { 
       query = query.Where(filter); 
      }     

      return orderBy != null ? orderBy(query).ToList() : query.ToList(); 
     } 

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

EDIT: изменение запроса обратно DbQuery

edit2: Фикс поставить позвонить в Include до Where, как Include должен быть вызван на DbSet или DbQuery. Причина, по которой это кажется случайным, заключается в том, что когда фильтра не было, то включенные вызовы вызывались в DbSet/DbQuery, где они должны были быть.

Нелегко заметить, что код имел звонок IQueryable<T>.Include ... который не является стандартным из коробки. Include находится на DbSet или DbQuery.

+0

Вещь в том, что я не передаю ни одной строки через браузеры. Вообще. URL имеет только идентификатор пользователя и все. «Клиент» - это простая строка константы «Клиент», никакие другие объекты не связаны с объектом «Пользователь», и, как уже упоминалось, он работает при входе в систему. – Krenom

+0

Да; хорошо http://stackoverflow.com/a/2929109/1099260 ответ имеет что-то, что может быть полезно. Мне также интересно, ваша переменная запроса имеет тип 'IQuerable ' (вместо exepected 'DbQuery '. IQueryable не имеет метода 'inlcude'. –

+0

@Qinton Изменение включений в массив ничего не изменило - но я думаю, что сохраню это, я так предпочитаю.Что касается того, почему это «IQueryable», я не помню сейчас. Было несколько месяцев назад, что сначала это было сказано, и до недавнего времени у нас не было никаких проблем с этим. Не то, чтобы кто-то из нас изменил его или какой-либо связанный код в последнее время - вся проблема сейчас нас превзошла. В качестве примечания мы используем EF5, если это имеет значение для наших обстоятельств. – Krenom

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