实体框架5 TSQL与SQL 2005调用存储过程不兼容

Sha*_*son 6 t-sql sql-server stored-procedures mvc-mini-profiler entity-framework-5

我正在使用Entity Framework 5,Code首先针对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);
    }
Run Code Online (Sandbox Code Playgroud)

我尝试的另一个变种是;

    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));
    }
Run Code Online (Sandbox Code Playgroud)

当我执行此操作时 - 我收到错误;

System.Data.SqlClient.SqlException(0x80131904):'SearchPotentialDuplicates'附近的语法不正确.

所以我用miniprofiler抓住了生成的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   
Run Code Online (Sandbox Code Playgroud)

我尝试将其复制并粘贴到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".
Run Code Online (Sandbox Code Playgroud)

这是一个新的sql 2008的事情(http://blogs.microsoft.co.il/blogs/bursteg/archive/2007/12/05/sql-server-2008-t-sql-declare-and-set-in- -in -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  
Run Code Online (Sandbox Code Playgroud)

工作良好!所以我的问题是实体框架是如何使用这种心理语法的?我已经做了一些谷歌搜索,人们谈论ProviderManifestToken,但这显然只有在进入一个完全不同的平台,如sql ce,而不是在sql版本之间时才需要.那么有一个我缺少的设置,还是我可以更改查询以强制它以不同的方式执行?

谢谢大家!

Sha*_*son 2

终于得到了这个工作-我尝试按照这篇文章http://blog.oneunicorn.com/2012/04/21/code-first-building-blocks/ (实体框架团队的Arthur Vickers)告诉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);
Run Code Online (Sandbox Code Playgroud)

现在执行以下 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'
Run Code Online (Sandbox Code Playgroud)

它在 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   
Run Code Online (Sandbox Code Playgroud)

这让我没有注意到我已经修复了这个问题几个小时!因此,我们得到的教训是 MiniProfiler 的 SQL 监控无法替代老式的 Sql Profiler!