저장 프로 시저와 함께 DbContext.Database.SqlQuery <TElement> (sql, params)를 사용하는 방법은 무엇입니까? EF 코드 우선 CTP5


250

세 가지 매개 변수가있는 저장 프로 시저가 있고 다음을 사용하여 결과를 반환하려고했습니다.

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

처음에는 SqlParameter객체를 매개 변수로 사용하려고 시도했지만 작동하지 않아서SqlException 다음 메시지와 함께 .

프로 시저 또는 함수 'mySpName'에는 제공되지 않은 '@ param1'매개 변수가 필요합니다.

그래서 내 질문은 매개 변수를 기대하는 저장 프로 시저 에서이 방법을 어떻게 사용할 수 있습니까?

감사.


어떤 버전의 SQL Server를 사용하고 있습니까? compat (90) 모드에서 2008에서 작동하는 코드에 문제가 있지만 2005 년에 실행할 때 구문 오류로 실패합니다.
Gats

4
@Gats-SQL 2005와 동일한 문제가있었습니다. 저장 프로 시저 이름 앞에 "EXEC"를 추가하십시오. 나는 미래의 참조를 위해 여기에이 정보를 게시 : stackoverflow.com/questions/6403930/...
댄 Mork

답변:


389

다음과 같은 방법으로 SqlParameter 인스턴스를 제공해야합니다.

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

3
이 메소드를 어떻게 널 입력 가능 유형으로 작동하게 하시겠습니까? nullable 소수로 이것을 시도했지만 소수가 null 일 때 매개 변수가 누락되었다는 오류가 발생합니다. 그러나 @DanMork가 언급 한 아래의 방법은 작동합니다.
Paul Johnson

2
DbNull.Valuenull 대신 전달 하면 문제가 해결됩니까?
Alireza

29
문맥에서와 같이 SqlParameter를 사용하지 않도록 \ @ p # 구문을 사용할 수도 있습니다. 출처 : msdn.microsoft.com/en-US/data/jj592907 . (참고 : 사용자 알림을 피하려면 \ @를 사용해야했습니다. 백 슬래시없이 읽어야합니다.)
Marco

3
DateTime 매개 변수를 사용하는 경우 이름과 값뿐만 아니라 매개 변수 유형도 지정해야합니다. 예 : dbContext.Database.SqlQuery <Invoice> ( "spGetInvoices @dateFrom, @dateTo", new SqlParameter {ParameterName = "dateFrom", SqlDbType = SqlDbType.DateTime, Value = startDate}, new SqlParameter {ParameterName = "dateTo", SqlDbType = SqlDbType.DateTime, 값 = endDate}); 또 다른 중요한 것은 매개 변수의 순서를 존중하는 것입니다.
Francisco Goldenstein

내가 잘못하고있는 일을 친절하게 확인할 수 있습니까? 나는 guidline을 따르지만 모든 stackoverflow.com/questions/27926598/
Toxic

129

또한 "sql"매개 변수를 형식 지정자로 사용할 수 있습니다.

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

이것을 투표해야했다. 답변으로 받아 들여지지는 않았지만 답변으로 선택된 솔루션보다 솔루션을 작성하는 것이 훨씬 쉽습니다.
Nikkoli

10
이 구문은 나에게 조금 관련이 있습니다. SQL 인젝션에 취약합니까? EF가 "EXEC mySpName @ Param1 ="을 실행 중이라고 가정하고 "x 'GO [악성 스크립트]"를 전송하여 문제를 일으킬 수 있습니까?
Tom Halladay

10
@TomHalladay는 SQL 주입의 위험이 없습니다.이 메소드는 @ 스타일 매개 변수와 동일한 유형에 따라 매개 변수를 인용하고 이스케이프합니다. 따라서 문자열 매개 변수의 경우 명령문에 따옴표없이 "SELECT * FROM Users WHERE email = {0}"을 사용합니다.
로스 맥 나브

내 경우에는 SP에 대한 선택적 매개 변수가 많이 있으며 SqlParameters를 사용하여 호출하지 않았지만이 형식은 트릭을 수행합니다. 처음에는 'EXEC'를 추가해야했습니다. 감사.
Onur Topal

1
이 답변은 선택적 매개 변수를 사용하여 proc에 매개 변수를 지정해야하는 경우에 유용합니다. 작동하지 않는 ProcName @optionalParam1 = @opVal1, @optionalParam2 = @opVal2 예 : 작동하는 예 :ProcName @optionalParam1 = {0}, @optionalParam2 = {1}
Garrison Neely

72

이 솔루션은 SQL Server 2005에만 해당됩니다.

여러분은 생명의 은인이지만 @Dan Mork가 말했듯이 EXEC를 믹스에 추가해야합니다. 나를 트립하고 있던 것은 :

  • Proc 이름 앞에 'EXEC'
  • Params 사이의 쉼표
  • Param Definitions에서 '@'잘라 내기 (비트가 필요한지 확실하지 않음)

:

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

21
+1. 높은 투표 응답 중 어느 것도 포함 exec하지 않지만 예외를 생략하면 예외가 있음을 확인할 수 있습니다.
Jordan Gray

감사합니다. 오류가 발생하여 EXEC를 추가했으며 오류가 사라졌습니다. 이상한 부분은 내가 context.Database.SqlQuery <EntityType> ( "ProcName '"+ param1 + "', '"+ param2 + "'"); 작동했지만 매개 변수를 추가하면 EXEC 키워드를 추가 할 때까지 작동하지 않았습니다.
Solmead 2019 년

2
참고 : exec키워드가 필요하지 않습니다 . 매개 변수에서 @를 제거하면 +1, 항상 엉망이됩니다.
Nathan Koop

+1, EXEC가 누락되어 'procName'근처의 구문이 잘못되었습니다.
A. 머레이

1
@Ziggler는 2005 년 이상입니까? EXEC 키워드는 주로 2005 년에 반대하는 사람들에게 문제가되었습니다.
Tom Halladay

15
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();
}

그것은 나를 위해 일하고있다 Assembly EntityFramework.dll, v4.4.0.0
Thulasiram

2
using (var context = new MyDataContext ())을 사용하는 경우 .ToList ()는 필수입니다.
Thulasiram

올바른 결과 집합을 얻으려면 .ToList ()가 필수적이라는 것을 알기 위해 많은 시간을 보냈습니다.
Halim

8

대부분의 답변은 SP의 매개 변수 순서에 의존하기 때문에 취하기 어렵습니다. Stored Proc의 매개 변수 이름을 지정하고 매개 변수화 된 값을 지정하는 것이 좋습니다.

SP를 호출 할 때 매개 변수 순서에 대해 걱정할 필요없이 명명 된 매개 변수를 사용하려면

ExecuteStoreQuery 및 ExecuteStoreCommand와 함께 SQL Server 명명 된 매개 변수 사용

최선의 방법을 설명합니다. Dan Mork의 대답보다 낫습니다.

  • 연결 문자열에 의존하지 않으며 SP에 정의 된 매개 변수의 순서에 의존하지 않습니다.

예 :

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

context.Database.SqlQuery<myEntityType>(cmdText, sqlParams)

"params"는 예약 된 키워드 인 것 같아서 그렇게 사용할 수 없다고 생각합니다. 그렇지 않으면 이것은 나에게 유용한 답변이었습니다. 감사!
ooXei1sh

@ ooXei1sh-고정, sqlParams변수 사용
Don Cheadle

당신이 할 수 @ 그것을 앞에 예약어를 사용하는,하지만 당신은 정말
StingyJack

6
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();

3

이 방법을 사용합니다.

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

Guids와 Datetimes에 빠지고 SqlQuery가 모든 형식을 수행하기 때문에 마음에 들었습니다.


1

@Tom Halladay의 대답은 shopuld도 null 값을 확인하고 매개 변수가 null 인 경우 DbNullable을 보내면 예외가 발생한다는 언급으로 정확합니다.

매개 변수화 된 쿼리 '...'에는 제공되지 않은 매개 변수 '@parameterName'이 필요합니다.

이 같은 것이 나를 도왔다

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)

0

두 개의 입력 매개 변수를 사용하고 SELECT 문을 사용하여 3 개의 값을 반환하는 저장 프로 시저를 호출 할 때 동일한 오류 메시지가 나타 났으며 EF Code First Approach에서 다음과 같은 문제를 해결했습니다.

 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; }
}

업데이트 : SQL Server 2005 누락 EXEC 키워드에 문제가있는 것처럼 보입니다. 그래서 모든 SQL SERVER 버전에서 작동 할 수 있도록 대답을 업데이트 하고 아래 줄 에 EXEC 를 추가 했습니다.

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

아래 링크를 참조하십시오. exec msdn.microsoft.com/en-us/data/jj592907.aspx
Ziggler

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.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.