Ham SQL Sorguları

Entity Framework Core, ilişkisel bir veritabanıyla çalışırken ham SQL sorgularını açmanıza olanak tanır. ham SQL sorguları, istediğiniz sorgu lınq kullanılarak ifade edilebilmesi yararlıdır. ham SQL sorguları ayrıca bir lınq sorgusunun kullanılması verimsiz bir SQL sorgusuna neden olursa da kullanılır. ham SQL sorguları, modelinizin bir parçası olan normal varlık türlerini veya anahtarsız varlık türlerini döndürebilir.

İpucu

Bu makalenin örneğini GitHub görüntüleyebilirsiniz.

temel ham SQL sorguları

FromSqlRawham SQL sorgusuna dayalı bir lınq sorgusuna başlamak için genişletme yöntemini kullanabilirsiniz. FromSqlRaw yalnızca doğrudan üzerinde olan sorgu köklerine uygulanabilir DbSet<> .

var blogs = context.Blogs
    .FromSqlRaw("SELECT * FROM dbo.Blogs")
    .ToList();

ham SQL sorguları, saklı bir yordamı yürütmek için kullanılabilir.

var blogs = context.Blogs
    .FromSqlRaw("EXECUTE dbo.GetMostPopularBlogs")
    .ToList();

Parametreleri geçirme

Uyarı

ham SQL sorguları için her zaman parametreleştirme kullanın

bir ham SQL sorgusuna kullanıcı tarafından sağlanmış herhangi bir değer alındığınızda, SQL ekleme saldırılarından kaçınmak için dikkatli olunması gerekir. bu tür değerlerin geçersiz karakterler içermediğini doğrulamaya ek olarak, her zaman değerleri SQL metinden ayrı gönderen parametreleştirme kullanın.

Özellikle, hiç bir birleştirilmiş veya enterpolasyonlu dize () ' i $"" doğrulanmamış kullanıcı tarafından sağlanmış değerlerle veya içine geçirmeyin FromSqlRawExecuteSqlRaw . FromSqlInterpolatedve ExecuteSqlInterpolated yöntemleri, SQL ekleme saldırılarına karşı koruma sağlamak için dize ilişkilendirme sözdiziminin kullanılmasına izin verir.

aşağıdaki örnek, SQL sorgu dizesinde bir parametre yer tutucusu ekleyerek ve ek bir bağımsız değişken sağlayarak, saklı yordama tek bir parametre geçirir. Bu söz dizimi sözdizimi gibi görünebilir String.Format , ancak sağlanan değer bir DbParameter ve yer tutucunun belirtildiği yerde oluşturulmuş parametre adına sarmalanır {0} .

var user = "johndoe";

var blogs = context.Blogs
    .FromSqlRaw("EXECUTE dbo.GetMostPopularBlogsForUser {0}", user)
    .ToList();

FromSqlInterpolated , öğesine benzerdir FromSqlRaw ancak dize ilişkilendirme söz dizimini kullanmanıza izin verir. Tıpkı gibi FromSqlRawFromSqlInterpolated yalnızca sorgu köklerinin üzerinde kullanılabilir. önceki örnekte olduğu gibi, değer bir öğesine dönüştürülür DbParameter ve SQL eklenmesine karşı savunmasız değildir.

var user = "johndoe";

var blogs = context.Blogs
    .FromSqlInterpolated($"EXECUTE dbo.GetMostPopularBlogsForUser {user}")
    .ToList();

Ayrıca bir DbParameter oluşturup bunu bir parametre değeri olarak sağlayabilirsiniz. normal bir SQL parametresi yer tutucusu kullanıldığı için, bir dize yer tutucusu yerine FromSqlRaw güvenli bir şekilde kullanılabilir:

var user = new SqlParameter("user", "johndoe");

var blogs = context.Blogs
    .FromSqlRaw("EXECUTE dbo.GetMostPopularBlogsForUser @user", user)
    .ToList();

FromSqlRawSQL sorgu dizesinde adlandırılmış parametreleri kullanmanıza olanak sağlar. bu, saklı yordam isteğe bağlı parametrelere sahip olduğunda yararlı olur:

var user = new SqlParameter("user", "johndoe");

var blogs = context.Blogs
    .FromSqlRaw("EXECUTE dbo.GetMostPopularBlogsForUser @filterByUser=@user", user)
    .ToList();

Not

Parametre sıralaması Entity Framework Core, parametreleri dizi sırasına göre geçirir . birden çok SqlParameter s geçirirken, SQL dizesindeki sıralama, saklı yordamın tanımındaki parametrelerin sırasıyla aynı olmalıdır. Bunun yapılmaması, yordam yürütüldüğünde tür dönüştürme özel durumlarına ve/veya beklenmeyen davranışlara neden olabilir.

LINQ ile oluşturma

lınq işleçleri kullanarak ilk ham SQL sorgusunun üzerine oluşturabilirsiniz. EF Core, bunu alt sorgu olarak değerlendirir ve veritabanında oluşturun. aşağıdaki örnek, bir Table-Valued işlevinden (tvf) seçen ham SQL sorgusu kullanır. Daha sonra, filtre uygulamak ve sıralamak için LINQ kullanarak buna bir bileşim yapın.

var searchTerm = "Lorem ipsum";

var blogs = context.Blogs
    .FromSqlInterpolated($"SELECT * FROM dbo.SearchBlogs({searchTerm})")
    .Where(b => b.Rating > 3)
    .OrderByDescending(b => b.Rating)
    .ToList();

Yukarıdaki sorgu aşağıdaki SQL oluşturur:

SELECT [b].[BlogId], [b].[OwnerId], [b].[Rating], [b].[Url]
FROM (
    SELECT * FROM dbo.SearchBlogs(@p0)
) AS [b]
WHERE [b].[Rating] > 3
ORDER BY [b].[Rating] DESC

IncludeYöntemi, diğer herhangi BIR LINQ sorgusuyla olduğu gibi ilgili verileri dahil etmek için kullanılabilir:

var searchTerm = "Lorem ipsum";

var blogs = context.Blogs
    .FromSqlInterpolated($"SELECT * FROM dbo.SearchBlogs({searchTerm})")
    .Include(b => b.Posts)
    .ToList();

EF Core sağlanan SQL alt sorgu olarak değerlendirildiğinden, lınq ile oluşturmak için ham SQL sorgusunun birleştirilebilir olması gerekir. üzerinde birleştirilebilen SQL sorguları SELECT anahtar sözcüğüyle başlar. ayrıca, geçilen SQL, bir alt sorgu üzerinde geçerli olmayan herhangi bir karakter veya seçenek içermemelidir, örneğin:

  • Sondaki noktalı virgül
  • SQL Server, sondaki sorgu düzeyi ipucu (örneğin, OPTION (HASH JOIN) )
  • SQL Server üzerinde ORDER BYOFFSET 0 veya TOP 100 PERCENTSELECT yan tümcesinde kullanılmamış bir yan tümce

SQL Server, saklı yordam çağrılarının üzerinde oluşturmaya izin vermez, bu nedenle, bu tür bir çağrıya ek sorgu işleçleri uygulama girişimleri geçersiz SQL neden olur. AsEnumerableAsAsyncEnumerableFromSqlRawFromSqlInterpolated EF Core bir saklı yordam üzerinden oluşturmaya çalıştığından emin olmak için ya da doğrudan yöntem veya yöntemler kullanın.

Değişiklik İzleme

Veya yöntemlerini kullanan sorgular FromSqlRaw , FromSqlInterpolated EF Core ' DEKI diğer LINQ sorgularıyla tam olarak aynı değişiklik izleme kurallarını izler. Örneğin, sorgu projeleri varlık türlerdir, sonuçlar varsayılan olarak izlenir.

aşağıdaki örnek, bir Table-Valued işlevinden (tvf) seçen bir ham SQL sorgusu kullanır, sonra yapılan çağrısıyla değişiklik izlemeyi devre dışı bırakır AsNoTracking :

var searchTerm = "Lorem ipsum";

var blogs = context.Blogs
    .FromSqlInterpolated($"SELECT * FROM dbo.SearchBlogs({searchTerm})")
    .AsNoTracking()
    .ToList();

Sınırlamalar

ham SQL sorguları kullanırken dikkat etmeniz için bazı sınırlamalar vardır:

  • SQL sorgu varlık türünün tüm özellikleri için veri döndürmelidir.
  • Sonuç kümesindeki sütun adları, özelliklerin eşlendiği sütun adlarıyla eşleşmelidir. Bu davranışın EF6 öğesinden farklı olduğunu aklınızda edin. EF6, ham SQL sorguları için sütun eşlemesine yoksayılan özelliği ve sonuç kümesi sütun adlarının özellik adlarıyla eşleşmesi gerekiyordu.
  • SQL sorgusu ilgili verileri içeremez. Bununla birlikte, çoğu durumda Include ilgili verileri ( Includeüzere) döndürmek için işlecini kullanarak sorgunun üzerine oluşturabilirsiniz.