6

Я использую Entity Framework 5, сначала код для базы данных SQL 2005. У меня есть репозиторий с методом, который выполняет хранимую процедуру. Метод выглядит следующим образом:Entity framework 5 TSQL несовместим с хранимыми процедурами вызова SQL 2005

public IEnumerable<PossibleDuplicateCustomer> GetPossibleDuplicates(Customer customer) 
    { 

     return DbContext.Database.SqlQuery<PossibleDuplicateCustomer>(
      "EXEC SearchPotentialDuplicates @CustomerId = {0}, @FirstName = {1}, @LastName = {2}, @dob = {3}", 
      customer.CustomerId, 
      customer.CustomerFirstName, 
      customer.CustomerLastName, 
      customer.Dob); 
    } 

Другой вариант, который я попробовал;

public IEnumerable<PossibleDuplicateCustomer> GetPossibleDuplicates(Customer customer) 
    { 
     return DbContext.Database.SqlQuery<PossibleDuplicateCustomer>(
      "SearchPotentialDuplicates @CustomerId, @FirstName, @LastName, @dob", 
      new SqlParameter("CustomerId", customer.CustomerId), 
      new SqlParameter("FirstName", customer.CustomerFirstName), 
      new SqlParameter("LastName", customer.CustomerLastName), 
      new SqlParameter("dob", customer.Dob)); 
    } 

Когда я выполняю это, я получаю сообщение об ошибке;

System.Data.SqlClient.SqlException (0x80131904): Неверный синтаксис рядом с 'SearchPotentialDuplicates'.

Итак, я схватил сгенерированный sql с помощью минипрофилера, который дал мне;

DECLARE @p0 int = 12644, 
    @p1 nvarchar(4) = N'adam', 
    @p2 nvarchar(3) = N'ant', 
    @p3 datetime = '1951-11-01T00:00:00' 

EXEC SearchPotentialDuplicates @CustomerId = @p0, @FirstName = @p1, @LastName = @p2, @dob = @p3 

Я попытался скопировать и вставить это в SSMS, и это дало ошибку, потому что синтаксис объявления и присвоения в одной строке не поддерживается

Msg 139, Level 15, State 1, Line 0 
Cannot assign a default value to a local variable. 
Msg 137, Level 15, State 2, Line 6 
Must declare the scalar variable "@p0". 

Это новый SQL 2008 вещь (http://blogs.microsoft.co.il/blogs/bursteg/archive/2007/12/05/sql-server-2008-t-sql-declare-and-set-in-the-same-statement.aspx) а не поддержка SQL 2005 - изменение запроса;

DECLARE @CustomerId int , 
    @FirstName nvarchar(25), 
    @LastName nvarchar(25) , 
    @dob datetime 

SET @CustomerId = 12645 
SET @FirstName = N'adam' 
SET @LastName = N'ant' 
SET @dob = '1951-11-01T00:00:00' 

exec SearchPotentialDuplicates @CustomerId, @FirstName, @LastName, @dob 

отлично работает! Итак, мой вопрос заключается в том, как структура сущности использует этот ментальный синтаксис? Я сделал несколько поисковых запросов, и люди говорят о ProviderManifestToken, но это, по-видимому, необходимо только при переходе на совершенно другую платформу, например sql ce, а не между версиями sql. Итак, есть ли параметр, который мне не хватает, или я могу изменить запрос, чтобы заставить его выполнить по-другому?

Спасибо всем!

+0

Возможно, они могли предоставить поддержку SQL Server 2005 с использованием старомодного объявления переменных, но я бы не назвал его «ментальным синтаксисом»; Я думаю, что это должен быть предпочтительный способ объявления переменной в T-SQL при условии, что вы не нацелены на что-либо старше, чем SQL Server 2008. –

+1

ха-ха, да, не поймите меня неправильно - это, безусловно, более чистый синтаксис опекуна. мне всегда приходилось разбивать объявление/назначение на две строки! Но это только лучше, если целевая платформа поддерживает его! – Shawson

+1

Как насчет ADO.Net и SqlCommand? Вы можете написать оболочку для вызова хранимых процедур с использованием этого подхода. Я знаю, что это старый метод, и он не отвечает на ваш вопрос, но он может решить вашу проблему. –

ответ

2

Наконец-то я получил эту работу. Я пробовал эту статью http://blog.oneunicorn.com/2012/04/21/code-first-building-blocks/ (Артур Викерс в команде фреймворка сущности), чтобы сообщить DbContext использовать синтаксис sql 2005. Поэтому, когда я создаю контекст, я делаю это;

var builder = new DbModelBuilder(); 
builder.Entity<PossibleDuplicateCustomer>(); 
var model = builder.Build(new DbProviderInfo("System.Data.SqlClient", "2005")); 
_compiledSql2005Model = model.Compile(); 

// OverdriveDbContext : DbContext 
var context = new OverdriveDbContext(
    nameOrConnectionString: "OverdriveConnectionString", 
    model: _compiledSql2005Model); 

В настоящее время выполняется следующий SQL;

exec sp_executesql N'EXEC SearchPotentialDuplicates @CustomerId, @FirstName, @LastName, @dob',N'@CustomerId int,@FirstName nvarchar(4),@LastName nvarchar(3),@dob datetime',@CustomerId=12645,@FirstName=N'adam',@LastName=N'ant',@dob='1951-11-01 00:00:00' 

, который отлично работает в SQL 2005. Слова предостережения, хотя - MiniProfiler (который я использую для мониторинга рамочной организации вызовов) неправильно показывает SQL выполняется как:

DECLARE @CustomerId int = 12645, 
    @FirstName nvarchar(4) = N'adam', 
    @LastName nvarchar(3) = N'ant', 
    @dob datetime = '1951-11-01T00:00:00' 

EXEC SearchPotentialDuplicates @CustomerId, @FirstName, @LastName, @dob 

который остановил меня, заметив, что я исправил это на несколько часов! Таким образом, урок, на котором работает мониторинг MiniProfiler, не заменяет старый добрый Sql Profiler!

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

  • Нет связанных вопросов^_^