Можно ли вручную изменить выражение IQueryable - PullRequest
5 голосов
/ 29 января 2012

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

Сначала я использую код EF для запроса таблицы обычным образом

_context.Set<Foo>().Where(f => f.Bar == 999);

, которая создает следующее выражение (я только что написал это, поэтому оно может быть неправильным).

{SELECT 
[Extent1].[Test] AS [Test], 
[Extent1].[Test2] AS [Test2], 
FROM [dbo].[Foo] AS [Extent1]
WHERE 19 = [Extent1].[Bar]}

Теперь можно ли вручную изменить этот запрос, чтобы изменить имя таблицы, скажем, Foo10?(вероятно, нет)

Если это не удастся, кто-нибудь знает, как я могу сначала "поздно связать" имя таблицы в коде первым?

Вам, наверное, интересно, "Почему грязный хак?"Как обычно, это устаревшая проблема с базой данных, которая имеет некоторые проблемы с дизайном и не может быть изменена.

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

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

Ответы [ 3 ]

2 голосов
/ 29 января 2012

Почему вы не используете TPT наследование для вашей модели?

Аналогично ответу @ Krizz, но вы избегаете использования динамического LINQ.

Используя ваш комментарий:

если конкретный параметр имеет значение 1, посмотрите в Foo1, если его 2 - в Foo2 и т. Д.

Итак, вы можете сделать это:

var query = ctx
   .Foos
   .OfMyType(value)
   .Where(f => f.Bar == 999) // f.Bar is on the base/abstract entity.
   .ToList();

Где OfMyType - это пользовательский метод расширения для IQueryable<T>:

public static IQueryable<T> OfMyType<T>(this IQueryable<T> source, string value)
{
   switch (value)
   {
      case "1":
         return source.OfType<Foo1>();
      case "2":
         return source.OfType<Foo2>();
      // etc, etc
   }
}

Большинство (если не все) свойств будут в абстрактной сущности "Foo", и вы создаетепроизводные сущности для каждой из таблиц, каждая из которых имеет свою собственную таблицу поддержки.

Таким образом, «потребляя» код (например, те, которые делают запросы), не нужно заботиться о разных таблицах / Foo, они простопередайте «магическое значение» в ваш репозиторий (надеюсь, вы его используете), затем вы можете тихо переключиться на нужный вам стол.

Будет ли это работать?

1 голос
/ 29 января 2012

Если у вас есть разумное количество таблиц, я бы добавил их все в модель и создал бы общий интерфейс, который будут реализованы всеми классами, а затем выбрал подходящую модель и использовал Dynamic Linq для запросов.

Я не уверен, что это работает, не проверял и не работал с "EF code-first", но я бы попробовал:

Допустим, у вашей таблицы (таблиц) Foo есть поля - Bar, Pub, X, и пусть X будет той, от которой зависит соответствующая таблица?

Тогда я бы определил интерфейс:

interface IFoo 
{
   int Bar { get; set; }
   string Pub { get; set; }
   int X { get; set; }
}

Тогда у каждой таблицы будет свой класс в модели:

[Table("Foo1")]
class Foo1 : IFoo 
{
   public int Bar { get; set; }
   public string Pub { get; set; }
   public int X { get; set; }
}

[Table("Foo2")]
class Foo2 : IFoo 
{
   public int Bar { get; set; }
   public string Pub { get; set; }
   public int X { get; set; }
}

Тогда вы можете отфильтровать их следующим образом:

 IQueryable GetAdequateFoo(int X)
 {
    switch (X) // you could use reflection here to dynamically call the given Set<Foo#>()
    {
       case 1:
         return _context.Set<Foo1>();
       case 2:
         return _context.Set<Foo2>();
       default:
         return null;
    }
 }

 IFoo GetFooByBarAndX(int bar, int X)
 {
    IQueryable context = GetAdequateFoo(X);
    return context.Where("it.Bar == @0", bar).Cast<IFoo>(); 
 }

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

0 голосов
/ 29 января 2012

Это не то, что я бы порекомендовал, но вы можете выполнить ToString () запрос, чтобы поместить оператор SQL в переменную, а затем строку заменить имя таблицы. Тогда SQL выполняет этот SQL?

Вонючий и смешной, но возможно?

...