2015-07-25 5 views
0

Я хотел бы иметь возможность использовать этот вид запроса с хранимой процедурой, как я делаю это с помощью простого DbSet<Balance>Пусть Хранимая процедура возврата IQueryable <T> не ObjectResult <TElement>

var bals = db.Balances 
       .Where(b => db.Balances.Any(b2 => b.Number.StartsWith(b2.Number)&&b2.Number!=b.Number)) 
       .ToList(); 

Это работает, но когда я пытаюсь она с импортируемой функции из хранимой процедуры:

var bals = db.GetCustomBalances("2015") 
      .Where(b => db.Balances 
          .Any(b2 => b.Number.StartsWith(b2.Number)&&b2.Number!=b.Number)) 
      .ToList(); 

это не работает:

не может перечислить перечисленные более одного раза

Как это решить?

UPDATE

Я заметил, что проблема в том, что хранимая процедура вызова db.GetCustomBalances("2015") возвращает ObjectResult<TElement> вместо IQueryable<TElement>, как с DbSet<TableName>

Как дать хранимую процедуру возврата IQueryable<T>, а не ObjectResult<TElement>?

+0

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

+0

это была опечатка ... – Bellash

ответ

1

Если вы действительно хотите это сделать, вы можете использовать трюк: открыть транзакцию, создать временную таблицу (таблицу # в SQL-сервере), выполнить процедуру, вставив результат непосредственно в эту временную таблицу (сделайте это, используя ExecuteStoreCommand api, но я бы предпочел бы абстрагировать и изолировать это с помощью интерфейса, так что если вы измените свой SGBD, вы также сможете изменить этот оператор sql), и что еще нужно сделать, так это сопоставить временную таблицу с объектом контекста способный создавать соединения с вашим набором результатов. Я сделал это некоторое время назад, используя другой трюк: создайте фальшивую таблицу с той же схемой, что и результат хранимой процедуры, сопоставьте ее в инфраструктуре Entity и используйте эту таблицу для соединений. Но вам придется подключить sql, который выполняется, чтобы заменить имя таблицы на временное имя таблицы. Вы можете это сделать, внедрив IDbCommandInterceptor и манипулировать командным тегом DbCommand перед его отправкой на сервер базы данных. Более подробную информацию об этом вы найдете здесь: http://www.skylinetechnologies.com/Blog/Article/2394/Entity-Framework-60-Intercepting-SQL-produced-by-EF.aspx Имейте в виду, что это решение не обязательно зависит от сервера sql, потому что почти любой SGBD имеет временные таблицы, и вы можете создать абстрактный завод, который служит для IDbCommandInterceptor для каждого поставщика SGBD. Еще одна вещь, о которой нужно помнить: не забудьте удалить временную таблицу, если вы повторно используете одно и то же соединение, иначе вам не придется беспокоиться, потому что каждый раз, когда соединение sql возвращается в пул, для этого соединения вызывается механизм очистки соединения. Например, в sql-сервере sp_resetconnection называется