Запрос данных с использованием Entity Framework из динамически создаваемой таблицы - PullRequest
8 голосов
/ 17 января 2012

TLDR; Как мне прочитать данные из таблицы, используя Entity Framework, если имя таблицы неизвестно во время компиляции?

Существует внешняя система, которая обрабатывает большую часть информации, а затем создает новую таблицу для каждого пакетного запуска и сохраняет некоторые данные в этой таблице. Расположение столбцов этих новых таблиц известно заранее, поэтому я сгенерировал модель данных объекта ADO.NET (файл edmx) из существующей базы данных, где есть таблица с точно такой же структурой столбцов. .

Исходная таблица в этой базе данных называется ResultTableTemplate, поэтому класс сущности, представляющий эту таблицу, также называется ResultTableTemplate.

Я пытаюсь выяснить, как использовать мою модель данных сущности ADO.NET для чтения из этих динамически созданных таблиц и получения обратно IEnumerable<ResultTableTemplate>. Что я сделал до сих пор это:

public IEnumerable<ResultTableTemplate> GetResultsFromTable(string tableName) {
    using (var context = new WorkdataEntities()) {
        var table = context.CreateQuery<ResultTableTemplate>("SELECT " +
            "ALL_THOSE_COLUMN_NAMES... " +
            "FROM " + tableName;

        var query = from item in table select item;

        return query.ToList();
    }
}

Когда я запускаю запрос, я получаю System.Data.EntitySqlException со следующим сообщением:

«ResultTable419828» не может быть разрешен в текущей области или контекст. Убедитесь, что все ссылочные переменные находятся в области видимости, что необходимые схемы загружены, и на эти пространства имен ссылаются правильно. Выражение доступа к члену рядом, строка 1, столбец 225.

ResultTable419828 - это значение tableName

Я пытался tableName + " AS ResultTableTemplate", но это не помогло.

Есть ли путь для меня вперед, или мне придется делать это без помощи Entity Framework?

EDIT: Теперь я понимаю, что текст запроса, который я пишу, не передается полностью до базового экземпляра SQL Server, а интерпретируется Entity Framework, который возвращает экземпляр ObjectQuery<ResultTableTemplate>, поэтому он ищет ResultTable419828 среди автоматически сгенерированных DbSet экземпляров Context.

Тем не менее, есть ли способ для меня добиться того, что мне нужно сделать?

РЕДАКТИРОВАТЬ: Спасибо Ладислав Мрнка . Теперь я делаю это:

public IEnumerable<ResultTableTemplate> GetResultsFromTable(string tableName) {
    using (var context = new WorkdataEntities()) {
        var query = context.ExecuteStoreQuery<ResultTableTemplate>("SELECT " +
            "ALL_THOSE_COLUMN_NAMES... " +
            "FROM " + tableName;

        return query.ToList();
    }
}

Ответы [ 2 ]

11 голосов
/ 17 января 2012

Это не возможно напрямую. Когда вы отображаете сущность на ResultTableTemplate, вы жестко задаете имя таблицы для этой сущности. Объекты могут отображаться только один раз (для каждой модели), поэтому во время выполнения каждый EF-запрос для этого объекта всегда приводит к запросу к таблице ResultTableTemplate.

Единственный способ изменить это поведение - это изменение файла сопоставления (SSDL) во время выполнения, что довольно уродливо, поскольку требует изменения XML-файла и его перезагрузки. Вам придется собирать MetadataWorkspace вручную каждый раз, когда вы меняете файл. Сборка MetadataWorkspace является одной из самых ресурсоемких операций в EF. При обычном запуске MetadataWorkspace создается только один раз за запуск приложения.

Есть простой обходной путь. Вы знаете имя таблицы и структуру таблицы - она ​​фиксированная. Так что используйте прямой SQL и используйте EF для материализации результата в ваш класс отображенного объекта:

var table = context.ExecuteStoreQuery<ResultTableTemplate>("SELECT ... FROM " + tableName);

Недостатком является то, что вы не можете использовать Linq в этом подходе, но ваше требование не очень хорошо подходит для EF.

0 голосов
/ 21 марта 2014

Попробуйте это;:)

string tableName = "MyTableTest";

// Fetch the table records dynamically
var tableData = ctx.GetType()
                .GetProperty(tableName)
                .GetValue(ctx, null);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...