diff --git a/entity-framework/core/querying/sql-queries.md b/entity-framework/core/querying/sql-queries.md index a3c59fc00e..4afe09b828 100644 --- a/entity-framework/core/querying/sql-queries.md +++ b/entity-framework/core/querying/sql-queries.md @@ -9,9 +9,6 @@ uid: core/querying/sql-queries Entity Framework Core allows you to drop down to SQL queries when working with a relational database. SQL queries are useful if the query you want can't be expressed using LINQ, or if a LINQ query causes EF to generate inefficient SQL. SQL queries can return regular entity types or [keyless entity types](xref:core/modeling/keyless-entity-types) that are part of your model. -> [!TIP] -> You can view this article's [sample](https://github.com/dotnet/EntityFramework.Docs/tree/main/samples/core/Querying/SqlQueries) on GitHub. - ## Basic SQL queries You can use to begin a LINQ query based on a SQL query: diff --git a/samples/core/Miscellaneous/ConfiguringDbContext/WithContextFactory/MyController.cs b/samples/core/Miscellaneous/ConfiguringDbContext/WithContextFactory/MyController.cs index d04fd4aa9a..8734218872 100644 --- a/samples/core/Miscellaneous/ConfiguringDbContext/WithContextFactory/MyController.cs +++ b/samples/core/Miscellaneous/ConfiguringDbContext/WithContextFactory/MyController.cs @@ -3,6 +3,8 @@ namespace WithContextFactory; +#pragma warning disable CS1998 // This async method lacks 'await' operators and will run synchronously. + public class MyController { #region Construct diff --git a/samples/core/Querying/SqlQueries/Blog.cs b/samples/core/Querying/SqlQueries/Blog.cs deleted file mode 100644 index 3bbf1c020a..0000000000 --- a/samples/core/Querying/SqlQueries/Blog.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; - -namespace EFQuerying.RawSQL; - -public class Blog -{ - public int BlogId { get; set; } - public string Url { get; set; } - public int? Rating { get; set; } - - public List Posts { get; set; } -} \ No newline at end of file diff --git a/samples/core/Querying/SqlQueries/BloggingContext.cs b/samples/core/Querying/SqlQueries/BloggingContext.cs deleted file mode 100644 index 0251c3525d..0000000000 --- a/samples/core/Querying/SqlQueries/BloggingContext.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -namespace EFQuerying.RawSQL; - -public class BloggingContext : DbContext -{ - public DbSet Blogs { get; set; } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .HasData( - new Blog { BlogId = 1, Url = @"https://devblogs.microsoft.com/dotnet", Rating = 5 }, - new Blog { BlogId = 2, Url = @"https://mytravelblog.com/", Rating = 4 }); - - modelBuilder.Entity() - .HasData( - new Post - { - PostId = 1, - BlogId = 1, - Title = "What's new", - Content = "Lorem ipsum dolor sit amet", - Rating = 5 - }, - new Post - { - PostId = 2, - BlogId = 2, - Title = "Around the World in Eighty Days", - Content = "consectetur adipiscing elit", - Rating = 5 - }, - new Post - { - PostId = 3, - BlogId = 2, - Title = "Glamping *is* the way", - Content = "sed do eiusmod tempor incididunt", - Rating = 4 - }, - new Post - { - PostId = 4, - BlogId = 2, - Title = "Travel in the time of pandemic", - Content = "ut labore et dolore magna aliqua", - Rating = 3 - }); - } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - optionsBuilder.UseSqlServer( - @"Server=(localdb)\mssqllocaldb;Database=EFQuerying.RawSQL;Trusted_Connection=True;ConnectRetryCount=0"); - } -} diff --git a/samples/core/Querying/SqlQueries/Post.cs b/samples/core/Querying/SqlQueries/Post.cs deleted file mode 100644 index 42572f2647..0000000000 --- a/samples/core/Querying/SqlQueries/Post.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace EFQuerying.RawSQL; - -public class Post -{ - public int PostId { get; set; } - public string Title { get; set; } - public string Content { get; set; } - public int Rating { get; set; } - - public int BlogId { get; set; } - public Blog Blog { get; set; } -} \ No newline at end of file diff --git a/samples/core/Querying/SqlQueries/Program.cs b/samples/core/Querying/SqlQueries/Program.cs deleted file mode 100644 index a44c3d24a9..0000000000 --- a/samples/core/Querying/SqlQueries/Program.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Data.SqlClient; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; - -namespace EFQuerying.RawSQL; - -#pragma warning disable EF1002 // Risk of vulnerability to SQL injection. -internal class Program -{ - private static async Task Main(string[] args) - { - using (var context = new BloggingContext()) - { - await context.Database.EnsureDeletedAsync(); - await context.Database.EnsureCreatedAsync(); - - await context.Database.ExecuteSqlRawAsync( - @"create function [dbo].[SearchBlogs] (@searchTerm nvarchar(max)) - returns @found table - ( - BlogId int not null, - Url nvarchar(max), - Rating int - ) - as - begin - insert into @found - select * from dbo.Blogs as b - where exists ( - select 1 - from [Post] as [p] - where ([b].[BlogId] = [p].[BlogId]) and (charindex(@searchTerm, [p].[Title]) > 0)) - - return - end"); - - await context.Database.ExecuteSqlRawAsync( - @"create procedure [dbo].[GetMostPopularBlogs] as - begin - select * from dbo.Blogs order by Rating - end"); - - await context.Database.ExecuteSqlRawAsync( - @"create procedure [dbo].[GetMostPopularBlogsForUser] @filterByUser nvarchar(max) as - begin - select * from dbo.Blogs order by Rating - end"); - } - - using (var context = new BloggingContext()) - { - var blogs = await context.Blogs - .FromSql($"SELECT * FROM dbo.Blogs") - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var blogs = await context.Blogs - .FromSql($"EXECUTE dbo.GetMostPopularBlogs") - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var user = "johndoe"; - - var blogs = await context.Blogs - .FromSql($"EXECUTE dbo.GetMostPopularBlogsForUser {user}") - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var user = new SqliteParameter("user", "johndoe"); - - var blogs = await context.Blogs - .FromSql($"EXECUTE dbo.GetMostPopularBlogsForUser @filterByUser={user}") - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var user = new SqliteParameter("user", "johndoe"); - - var blogs = await context.Blogs - .FromSql($"EXECUTE dbo.GetMostPopularBlogsForUser {user}") - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var columnName = "Url"; - var columnValue = new SqliteParameter("columnValue", "http://SomeURL"); - - var blogs = await context.Blogs - .FromSqlRaw($"SELECT * FROM [Blogs] WHERE {columnName} = @columnValue", columnValue) - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var searchTerm = "Lorem ipsum"; - - var blogs = await context.Blogs - .FromSql($"SELECT * FROM dbo.SearchBlogs({searchTerm})") - .Where(b => b.Rating > 3) - .OrderByDescending(b => b.Rating) - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var searchTerm = "Lorem ipsum"; - - var blogs = await context.Blogs - .FromSql($"SELECT * FROM dbo.SearchBlogs({searchTerm})") - .Include(b => b.Posts) - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var searchTerm = "Lorem ipsum"; - - var blogs = await context.Blogs - .FromSql($"SELECT * FROM dbo.SearchBlogs({searchTerm})") - .AsNoTracking() - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var ids = await context.Database - .SqlQuery($"SELECT [BlogId] FROM [Blogs]") - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var overAverageIds = await context.Database - .SqlQuery($"SELECT [BlogId] AS [Value] FROM [Blogs]") - .Where(id => id > context.Blogs.Average(b => b.BlogId)) - .ToListAsync(); - } - - using (var context = new BloggingContext()) - { - var rowsModified = await context.Database.ExecuteSqlAsync($"UPDATE [Blogs] SET [Url] = NULL"); - } - } -} diff --git a/samples/core/Querying/SqlQueries/SqlQueries.csproj b/samples/core/Querying/SqlQueries/SqlQueries.csproj deleted file mode 100644 index 3e19393e44..0000000000 --- a/samples/core/Querying/SqlQueries/SqlQueries.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - Exe - net8.0 - EFQuerying.SqlQueries - EFQuerying.SqlQueries - - - - - - - - diff --git a/samples/core/Samples.sln b/samples/core/Samples.sln index 3bbd6d00f9..a27ec19a69 100644 --- a/samples/core/Samples.sln +++ b/samples/core/Samples.sln @@ -51,8 +51,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientEvaluation", "Queryin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tracking", "Querying\Tracking\Tracking.csproj", "{CCD901FE-20C8-4DC0-AD9C-8B8333EE277B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SqlQueries", "Querying\SqlQueries\SqlQueries.csproj", "{63B6747C-470D-4561-A3A2-3C024747BE3B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComplexQuery", "Querying\ComplexQuery\ComplexQuery.csproj", "{AD0BF60E-B46C-4181-BF43-D68801E5D259}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tags", "Querying\Tags\Tags.csproj", "{2343A153-5832-41B9-A1FF-D80D3107A1DA}" @@ -291,10 +289,6 @@ Global {CCD901FE-20C8-4DC0-AD9C-8B8333EE277B}.Debug|Any CPU.Build.0 = Debug|Any CPU {CCD901FE-20C8-4DC0-AD9C-8B8333EE277B}.Release|Any CPU.ActiveCfg = Release|Any CPU {CCD901FE-20C8-4DC0-AD9C-8B8333EE277B}.Release|Any CPU.Build.0 = Release|Any CPU - {63B6747C-470D-4561-A3A2-3C024747BE3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {63B6747C-470D-4561-A3A2-3C024747BE3B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {63B6747C-470D-4561-A3A2-3C024747BE3B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {63B6747C-470D-4561-A3A2-3C024747BE3B}.Release|Any CPU.Build.0 = Release|Any CPU {AD0BF60E-B46C-4181-BF43-D68801E5D259}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AD0BF60E-B46C-4181-BF43-D68801E5D259}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD0BF60E-B46C-4181-BF43-D68801E5D259}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -587,7 +581,6 @@ Global {524AE4A6-A15F-466C-AED3-CDF3209E4394} = {1AD64707-0BE0-48B0-A803-916FF96DCB4F} {AF8B71E6-454F-4B66-98EE-2128B415EC45} = {1AD64707-0BE0-48B0-A803-916FF96DCB4F} {CCD901FE-20C8-4DC0-AD9C-8B8333EE277B} = {1AD64707-0BE0-48B0-A803-916FF96DCB4F} - {63B6747C-470D-4561-A3A2-3C024747BE3B} = {1AD64707-0BE0-48B0-A803-916FF96DCB4F} {AD0BF60E-B46C-4181-BF43-D68801E5D259} = {1AD64707-0BE0-48B0-A803-916FF96DCB4F} {2343A153-5832-41B9-A1FF-D80D3107A1DA} = {1AD64707-0BE0-48B0-A803-916FF96DCB4F} {17A82259-1B8A-4199-A564-AC250F51360E} = {1AD64707-0BE0-48B0-A803-916FF96DCB4F}