2016-10-11 3 views
0

Я добавил следующий метод расширенияDbSet включает метод расширения зацикливания

/// <summary> 
    /// Provides a statically typed interface for db includes 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="set">The set.</param> 
    /// <param name="includes">The includes.</param> 
    /// <returns>DbSet&lt;T&gt;.</returns> 
    public static DbSet<T> Include<T>(this DbSet<T> set, params Expression<Func<T, object>>[] includes) where T : class 
    { 
     if (includes != null) 
     { 
      foreach (var expression in includes) 
      { 
       set.Include(expression); 
      } 
     } 
     return set; 
    } 

Это базируется на коде хранилища я нашел здесь

https://github.com/carbonrobot/FullStackEF/tree/master/src

Однако, когда я использую это с нижеследующее

public ServiceResponse<Town> Get(int id) 
    { 
     Func<Patient> func = delegate 
     { 
      using (var context = _contextFactory()) 
      { 
       return context.Get<Town>(id, x => x.County); 
      } 
     }; 
     return this.Execute(func); 
    } 

Место, где находится городской класс, содержит округ en Tity.

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

Любые идеи, что я делаю неправильно здесь?

ответ

1

В этом методе есть несколько ошибок.

Метод DbExtensions.Include имеет следующую подпись:

public static IQueryable<T> Include<T, TProperty>(
    this IQueryable<T> source, 
    Expression<Func<T, TProperty>> path 
) 
where T : class 

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

Кроме того, поскольку метод вызывает Include на set переменную типа DbSet<T>, который более конкретен, чем IQueryable<T>, а аргумент соответствует подписи пользовательского метода, компилятор просто вызывает тот же метод, поэтому StackOverflowException.

С этим, как говорится, вот это правильная пользовательский метод подпись и реализация:

public static IQueryable<T> Include<T>(this DbSet<T> set, params Expression<Func<T, object>>[] includes) 
    where T : class 
{ 
    var result = set.AsQueryable(); 
    if (includes != null) 
    { 
     foreach (var expression in includes) 
     { 
      result = result.Include(expression); 
     } 
    } 
    return result; 
} 
+0

спасибо за подробные объяснения. Один вопрос, хотя, поскольку репо использует DbSet, возвращаемый для цепочки методов. ie.include (includes) .find (id) Как метод расширения возвращает IQueryable (в отличие от DbSet Я теряю способность связывать любые идеи с этим? –

+0

Хм, это звучит неразрешимо, но 'Include' doesn ' t работать с 'Find' в любом случае, поэтому я думаю, что нет смысла связываться с' Find'. Регулярные цепочки LINQ должны работать. Обоснование заключается в том, что результат 'Include' больше не' DbSet' –

+0

Ok так что вы бы рекомендовали просто .include (include) .select (x => x.Id == id); (в отношении примера поиска). Чтобы отфильтровать результаты запроса? –

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