如何使用存储过程DbContext.Database.SqlQuery <telement>(sql,params)? EF Code First CTP5 </telement>

时间:2011-02-02 11:01:51

标签: c# sql ado.net linq-to-entities entity-framework-ctp5

我有一个包含三个参数的存储过程,我一直在尝试使用以下命令返回结果:

context.Database.SqlQuery<myEntityType>("mySpName", param1, param2, param3);

首先,我尝试使用SqlParameter个对象作为参数,但这不起作用,并使用以下消息抛出SqlException

  

过程或函数'mySpName'需要参数'@param1',这是未提供的。

所以我的问题是如何将这个方法用于需要参数的存储过程?

感谢。

10 个答案:

答案 0 :(得分:363)

您应该按以下方式提供SqlParameter实例:

context.Database.SqlQuery<myEntityType>(
    "mySpName @param1, @param2, @param3",
    new SqlParameter("param1", param1),
    new SqlParameter("param2", param2),
    new SqlParameter("param3", param3)
);

答案 1 :(得分:122)

此外,您可以使用“sql”参数作为格式说明符:

context.Database.SqlQuery<MyEntityType>("mySpName @param1 = {0}", param1)

答案 2 :(得分:70)

此解决方案仅适用于SQL Server 2005

你们是救生员,但正如@Dan Mork所说,你需要在混合中加入EXEC。绊倒我的是:

  • Proc名称前的'EXEC'
  • Params之间的逗号
  • 在Param上砍掉'@' 定义(不确定该位是否需要)。

context.Database.SqlQuery<EntityType>(
    "EXEC ProcName @param1, @param2", 
    new SqlParameter("param1", param1), 
    new SqlParameter("param2", param2)
);

答案 3 :(得分:13)

return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 });

//或

using(var context = new MyDataContext())
{
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 }).ToList();
}

//或

using(var context = new MyDataContext())
{
object[] parameters =  { param1, param2, param3 };

return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
parameters).ToList();
}

//或

using(var context = new MyDataContext())
{  
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
param1, param2, param3).ToList();
}

答案 4 :(得分:4)

大多数答案都很脆弱,因为它们依赖于SP参数的顺序。最好命名存储过程的参数并为这些参数值提供参数值。

在调用SP时使用命名参数,而不必担心参数的顺序

Using SQL Server named parameters with ExecuteStoreQuery and ExecuteStoreCommand

描述最佳方法。比丹·莫克的回答更好。

  • 不依赖于串联字符串,也不依赖于SP中定义的参数顺序。

E.g:

CREATE TABLE foo (
    theKey int NOT NULL IDENTITY(1,1) PRIMARY KEY,
    someInt int
)

CREATE TABLE bar (
    theKey int NOT NULL IDENTITY(1,1) PRIMARY KEY,
    otherInt int
)

CREATE TABLE output (
    theKey int NOT NULL PRIMARY KEY,
    someInt int,
    otherInt int,
    valueDifference int
)

INSERT INTO output ( theKey, someInt, otherInt, valueDifference )
SELECT
    foo.theKey,
    foo.someInt,
    bar.otherInt,
    foo.someInt - bar.otherInt AS valueDifference
FROM
    foo
    INNER JOIN bar ON foo.theKey = bar.theKey

答案 5 :(得分:3)

db.Database.SqlQuery<myEntityType>("exec GetNewSeqOfFoodServing @p0,@p1,@p2 ", foods_WEIGHT.NDB_No, HLP.CuntryID, HLP.ClientID).Single()

db.Database.SqlQuery<myEntityType>(
    "exec GetNewSeqOfFoodServing @param1, @param2", 
    new SqlParameter("param1", param1), 
    new SqlParameter("param2", param2)
);

var cmdText = "exec [DoStuff] @Name = @name_param, @Age = @age_param";
var @params = new[]{
   new SqlParameter("name_param", "Josh"),
   new SqlParameter("age_param", 45)
};

db.Database.SqlQuery<myEntityType>(cmdText, @params)

db.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 }).ToList();

答案 6 :(得分:2)

我使用这种方法:

var results = this.Database.SqlQuery<yourEntity>("EXEC [ent].[GetNextExportJob] {0}", ProcessorID);

我喜欢它,因为我只是放入Guids和Datetimes,SqlQuery为我执行所有格式化。

答案 7 :(得分:1)

@Tom Halladay的答案是正确的,提到你shopuld也检查空值并发送DbNullable如果params为null,因为你会得到一个例外

参数化查询&#39; ...&#39;需要参数&#39; @ parameterName&#39;,这是未提供的。

这样的事情帮助了我

public static object GetDBNullOrValue<T>(this T val)
{
    bool isDbNull = true;
    Type t = typeof(T);

    if (Nullable.GetUnderlyingType(t) != null)
        isDbNull = EqualityComparer<T>.Default.Equals(default(T), val);
    else if (t.IsValueType)
        isDbNull = false;
    else
        isDbNull = val == null;

    return isDbNull ? DBNull.Value : (object) val;
}

(方法归功于https://stackoverflow.com/users/284240/tim-schmelter

然后使用它:

new SqlParameter("@parameterName", parameter.GetValueOrDbNull())

或其他解决方案,更简单,但不是通用的:

new SqlParameter("@parameterName", parameter??(object)DBNull.Value)

答案 8 :(得分:0)

当我在调用存储过程时,我有相同的错误消息,该存储过程接受两个输入参数并使用SELECT语句返回3个值,我在EF Code First方法中解决了如下问题

 SqlParameter @TableName = new SqlParameter()
        {
            ParameterName = "@TableName",
            DbType = DbType.String,
            Value = "Trans"
        };

SqlParameter @FieldName = new SqlParameter()
        {
            ParameterName = "@FieldName",
            DbType = DbType.String,
            Value = "HLTransNbr"
        };


object[] parameters = new object[] { @TableName, @FieldName };

List<Sample> x = this.Database.SqlQuery<Sample>("EXEC usp_NextNumberBOGetMulti @TableName, @FieldName", parameters).ToList();


public class Sample
{
    public string TableName { get; set; }
    public string FieldName { get; set; }
    public int NextNum { get; set; }
}

UPDATE :看起来SQL SERVER 2005缺少EXEC关键字正在创建问题。因此,为了使其能够与所有SQL SERVER版本一起使用,我更新了我的答案并在下面的行中添加了 EXEC

 List<Sample> x = this.Database.SqlQuery<Sample>(" EXEC usp_NextNumberBOGetMulti @TableName, @FieldName", param).ToList();

答案 9 :(得分:0)

我确实使用EF 6.x挖过这样的东西:

using(var db = new ProFormDbContext())
            {
                var Action = 1; 
                var xNTID = "A239333";

                var userPlan = db.Database.SqlQuery<UserPlan>(
                "AD.usp_UserPlanInfo @Action, @NTID", //, @HPID",
                new SqlParameter("Action", Action),
                new SqlParameter("NTID", xNTID)).ToList();


            }

不要在sqlparameter上加倍学习,以至于有些人为此而烦恼

var Action = new SqlParameter("@Action", 1);  // Don't do this, as it is set below already.