Saklı yordam ile DbContext.Database.SqlQuery <TElement> (sql, params) nasıl kullanılır? EF Kodu Önce CTP5


250

Üç parametre olan bir saklı yordam var ve ben sonuçları döndürmek için aşağıdaki kullanmaya çalışıyorum:

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

İlk başta SqlParameternesneleri param olarak kullanmayı denedim ama bu işe yaramadı ve SqlExceptionaşağıdaki mesajla bir attı :

'MySpName' yordamı veya işlevi, sağlanmayan '@ param1' parametresini bekliyor.

Benim sorum, bu yöntemi parametreleri bekleyen bir saklı yordam ile nasıl kullanabilirsiniz?

Teşekkürler.


Hangi SQL Server sürümünü kullanıyorsunuz? Uyumlu (90) modunda 2008'de çalışan kod ile ilgili sorun yaşıyorum, ancak 2005'e karşı çalıştırdığınızda bir sözdizimi hatası ile başarısız olur.
Gats

4
@Gats - SQL 2005 w / aynı sorunu vardı. Saklı yordam adından önce "EXEC" ekleyin. Bu bilgiyi ileride başvurmak üzere buraya gönderdim: stackoverflow.com/questions/6403930/…
Dan Mork

Yanıtlar:


389

SqlParameter örneklerini aşağıdaki şekilde sağlamalısınız:

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

3
Bu yöntemin nullable türleriyle nasıl çalışmasını sağlarsınız? Bunu nullable ondalıklarla denedim, ancak ondalık sayılar boş olduğunda parametre eksik olduğunu söyleyerek hata alıyorum. Ancak, @DanMork tarafından belirtilen yöntem aşağıdadır.
Paul Johnson

2
DbNull.ValueBoş değer yerine geçmek sorunu çözüyor mu?
Alireza

29
\ @ P # sözdizimini bağlamda da SqlParameter kullanmaktan kaçınmak için kullanabilirsiniz.Database.SqlQuery <myEntityType ("mySpName \ @ p0, \ @ p1, \ @ p2", param1, param2, param3). Kaynak: msdn.microsoft.com/en-US/data/jj592907 . (Not: kullanıcı bildirimlerini önlemek için \ @ kullanmak zorundaydı, ters eğik çizgi olmadan okunmalıdır.)
Marco

3
DateTime parametrelerini kullanıyorsanız, yalnızca ad ve değeri değil, parametre türünü de belirtmeniz gerekir. Örneğin: dbContext.Database.SqlQuery <Invoice> ("spGetInvoices @dateFrom, @dateTo", yeni SqlParameter {ParameterName = "dateFrom", SqlDbType = SqlDbType.DateTime, Value = startDate}, yeni SqlParameter {parametre "," SqlDbType = SqlDbType.DateTime, Değer = endDate}); Bir diğer önemli şey parametrelerin sırasına saygı göstermektir.
Francisco Goldenstein

lütfen neyi yanlış yaptığımı kontrol edebilir misin seni takip ettim ama hiçbir etkisi yok stackoverflow.com/questions/27926598/…
Toxic

129

Ayrıca, biçim belirteci olarak "sql" parametresini kullanabilirsiniz:

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

Bunu oylamalıydım. Cevap olarak kabul edilmese de, çözüm yazmak cevap olarak seçilen çözümden çok daha kolay.
Nikkoli

10
Bu sözdizimi beni biraz ilgilendiriyor. SQL enjeksiyonuna açık olur mu? EF'in "EXEC mySpName @ Param1 =" çalıştırdığını ve "x 'GO [kötü amaçlı komut dosyası]" gönderip bazı sorunlara neden olabileceğini varsayabilirim.
Tom Halladay

10
@TomHalladay SQL enjeksiyonu riski yoktur - yöntem, @ stili parametrelerine benzer şekilde türlerine göre parametreleri alıntılayıp kaçacaktır. Bu nedenle, bir dize parametresi için, ifadenizde tırnak işaretleri olmadan "SELECT * FROM Kullanıcılarından E-posta = {0}" kullanırsınız.
Ross McNab

benim durumumda SP için birçok isteğe bağlı parametre var ve SqlParameters ile çağrılar işe yaramadı ama bu format hile yapmak, sadece başlangıçta 'EXEC' eklemek zorunda kaldı. Teşekkürler.
Onur Topal

1
Bu yanıt, isteğe bağlı parametreleri olan bir proc'a parametreler belirtmeniz gerektiğinde yararlıdır. İşe yaramaz ProcName @optionalParam1 = @opVal1, @optionalParam2 = @opVal2 örnek : İşe ProcName @optionalParam1 = {0}, @optionalParam2 = {1}
yarayan

72

Bu çözüm (yalnızca) SQL Server 2005 içindir

Siz hayat kurtarıcısınız, ama @ Dan Mork'un dediği gibi karışıma EXEC eklemeniz gerekiyor. Beni harekete geçiren şey şuydu:

  • Proc Adından önce 'EXEC'
  • Params Arasındaki Virgüller
  • Param Tanımlarında '@' kesilmesi (bitin gerekli olduğundan emin değilim).

:

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

21
+1. Yüksek oylanan cevapların hiçbiri içermez exec, ancak atlarsam bir istisna aldığımı doğrulayabilirim.
Jordan Gray

Teşekkür ederim, bir hata alıyordum, EXEC ekledim ve hata gitti. Garip bölüm, context.Database.SqlQuery <EntityType> ("ProcName '" + param1 + "', '" + param2 + "'"); işe yaradı, ancak parametre eklersem EXEC anahtar kelimesini ekleyene kadar çalışmadı.
Solmead

2
Bilginize: execAnahtar kelimeye gerek duymuyorum . Params @ @ kaldırılması için +1, her zaman beni berbat.
Nathan Koop

+1, EXEC eksik ve mesaj ile SqlExceptions almaya devam etti: 'procName' yakınındaki yanlış sözdizimi.
A. Murray

1
@Ziggler 2005 veya daha yeni misin? EXEC anahtar kelimesi, 2005 yılına karşı çıkanlar için önemli bir konudur.
Tom Halladay

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

//Veya

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

//Veya

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

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

//Veya

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

Benim için Meclis EntityFramework.dll, v4.4.0.0 için çalışıyor
Thulasiram

2
(var context = new MyDataContext ()) kullanarak kullanıyorsanız .ToList () zorunludur.
Thulasiram

Doğru sonuç kümesini almak için .ToList () yönteminin zorunlu olduğunu keşfetmek için biraz zaman harcadım.
Halim

8

Cevapların çoğu kırılgandır çünkü SP parametrelerinin sırasına dayanırlar. Depolanmış Proc'un parametrelerini adlandırmak ve bunlara parametreli değerler vermek daha iyidir.

SP'nizi çağırırken parametrelerin sırası hakkında endişelenmeden Adlandırılmış parametreler kullanmak için

ExecuteStoreQuery ve ExecuteStoreCommand ile SQL Server adlı parametreleri kullanma

En iyi yaklaşımı açıklar. Dan Mork'un cevabından daha iyi.

  • Dizeleri birleştirmeye ve SP'de tanımlanan parametrelerin sırasına bağlı değildir.

Örneğin:

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)

Görünüşe göre "params" ayrılmış bir anahtar kelime, bu yüzden bu şekilde kullanabilirsiniz sanmıyorum. Aksi takdirde bu benim için yararlı bir cevaptı. Teşekkürler!
ooXei1sh

@ ooXei1sh - sabit, sqlParamsdeğişken kullanarak
Don Cheadle

Eğer yapabilirsiniz @ öneki ayrılmış bir kelime kullanmak, ama sen gerçekten olmamalı
StingyJack

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

veya

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

veya

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)

veya

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

3

Bu yöntemi kullanıyorum:

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

Seviyorum çünkü sadece Rehberler ve Tarihler düşüyor ve SqlQuery benim için tüm biçimlendirme yapar.


1

@Tom Halladay'ın cevabı, null değerleri de kontrol edip parametreler null olursa DbNullable gönderirseniz,

Parametrelendirilmiş '...' sorgusu, sağlanmayan '@parameterName' parametresini bekliyor.

Böyle bir şey bana yardımcı oldu

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

(yöntemin kredisi https://stackoverflow.com/users/284240/tim-schmelter adresine gider )

Sonra şöyle kullanın:

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

ya da daha basit, ama genel olmayan başka bir çözüm:

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

0

SELECT ifadesini kullanarak iki giriş parametresi alan ve 3 değer döndüren bir saklı yordam çağırma ile çalışırken aynı hata iletisi vardı ve EF Kod İlk Yaklaşımı aşağıdaki gibi sorunu çözdü

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

GÜNCELLEME : Görünüşe göre SQL SERVER 2005 eksik EXEC anahtar kelime sorun yaratıyor. Bu yüzden tüm SQL SERVER sürümleriyle çalışmasına izin vermek için cevabımı güncelledim ve aşağıdaki satırda EXEC ekledim

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

Lütfen aşağıdaki bağlantıya bakın. Exec kullanmanıza gerek yoktur msdn.microsoft.com/en-us/data/jj592907.aspx
Ziggler

0

Ben EF 6.x ile benim gibi yaptım:

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


            }

Bazı insanlar değişkenlerine bunu yaparak yakılırlar.

var Action = new SqlParameter("@Action", 1);  // Don't do this, as it is set below already.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.