Entity Framework Core 中的存储过程超厉害!从定义到调用全攻略,提升性能与安全性!

简介: 【8月更文挑战第31天】在现代软件开发中,数据库操作效率至关重要。Entity Framework Core(EF Core)作为强大的对象关系映射(ORM)框架,支持存储过程,可提升数据库操作的性能、安全性和可维护性。本文详细介绍如何在 EF Core 中定义、配置及调用存储过程,并提供最佳实践建议,包括性能优化、安全性增强、代码可维护性提升以及参数化查询等。通过遵循这些指导原则,开发者能够充分利用存储过程的优势,显著提高应用程序质量和性能。附带完整示例代码,展示从定义实体类到调用存储过程的全过程。

在现代软件开发中,数据库的高效操作至关重要。Entity Framework Core(EF Core)作为一个强大的对象关系映射(ORM)框架,提供了对存储过程的支持。使用存储过程可以提高数据库操作的性能、安全性和可维护性。以下是在 EF Core 中使用存储过程的最佳实践。

一、存储过程的定义

首先,在数据库中定义存储过程。存储过程是一组预先编译好的 SQL 语句,可以接受参数并返回结果。例如,以下是一个在 SQL Server 中定义的简单存储过程,用于查询特定条件的客户:

CREATE PROCEDURE GetCustomersByCity
    @City nvarchar(50)
AS
BEGIN
    SELECT * FROM Customers WHERE City = @City;
END

二、在 EF Core 中配置存储过程

在 EF Core 中,需要在数据库上下文类中配置存储过程。可以使用OnModelCreating方法来指定存储过程的映射。以下是一个示例:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyApp.Data
{
   
    public class MyDbContext : DbContext
    {
   
        public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
        {
   
        }

        public DbSet<Customer> Customers {
    get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
   
            modelBuilder.Entity<Customer>().HasNoKey().ToSqlQuery("EXEC GetCustomersByCity @City");
        }
    }
}

在上述代码中,我们在OnModelCreating方法中使用ToSqlQuery方法将存储过程映射到Customer实体。注意,这里的HasNoKey表示该查询结果没有主键,因为存储过程可能返回多个结果集,不一定有明确的主键。

三、调用存储过程

在 EF Core 中,可以通过FromSqlRawFromSqlInterpolated方法来调用存储过程。以下是一个示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyApp.Services
{
   
    public class CustomerService
    {
   
        private readonly MyDbContext _dbContext;

        public CustomerService(MyDbContext dbContext)
        {
   
            _dbContext = dbContext;
        }

        public async Task<List<Customer>> GetCustomersByCity(string city)
        {
   
            return await _dbContext.Customers.FromSqlInterpolated($"EXEC GetCustomersByCity @City={city}").ToListAsync();
        }
    }
}

在上述代码中,CustomerService类通过构造函数注入了MyDbContext。在GetCustomersByCity方法中,使用FromSqlInterpolated方法调用存储过程,并传递城市名称作为参数。

四、最佳实践建议

  1. 性能优化:存储过程可以预先编译,减少了 SQL 语句的解析和优化时间,从而提高性能。对于复杂的查询或频繁执行的操作,使用存储过程可以显著提高性能。
  2. 安全性:存储过程可以限制对数据库的直接访问,提高安全性。可以通过授予存储过程执行权限,而不是直接授予对表的访问权限,来控制用户对数据的访问。
  3. 可维护性:将业务逻辑封装在存储过程中,可以提高代码的可维护性。如果业务逻辑发生变化,只需要修改存储过程,而不需要修改应用程序中的多个地方。
  4. 参数化查询:在存储过程中使用参数化查询可以防止 SQL 注入攻击。确保对用户输入进行适当的验证和参数化,以提高安全性。
  5. 测试:在使用存储过程时,确保对其进行充分的测试。可以使用单元测试来验证存储过程的正确性和性能。

总之,在 Entity Framework Core 中使用存储过程可以提高数据库操作的性能、安全性和可维护性。通过正确地定义、配置和调用存储过程,并遵循最佳实践建议,可以更好地利用存储过程的优势,提高应用程序的质量和性能。

以下是一个完整的示例代码,展示了在 EF Core 中使用存储过程的过程:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyApp
{
   
    public class Customer
    {
   
        public int Id {
    get; set; }
        public string Name {
    get; set; }
        public string City {
    get; set; }
    }

    public class MyDbContext : DbContext
    {
   
        public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
        {
   
        }

        public DbSet<Customer> Customers {
    get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
   
            modelBuilder.Entity<Customer>().HasNoKey().ToSqlQuery("EXEC GetCustomersByCity @City");
        }
    }

    public class CustomerService
    {
   
        private readonly MyDbContext _dbContext;

        public CustomerService(MyDbContext dbContext)
        {
   
            _dbContext = dbContext;
        }

        public async Task<List<Customer>> GetCustomersByCity(string city)
        {
   
            return await _dbContext.Customers.FromSqlInterpolated($"EXEC GetCustomersByCity @City={city}").ToListAsync();
        }
    }

    class Program
    {
   
        static async Task Main()
        {
   
            var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
            optionsBuilder.UseSqlServer("YourConnectionString");

            using (var dbContext = new MyDbContext(optionsBuilder.Options))
            {
   
                var customerService = new CustomerService(dbContext);

                var customers = await customerService.GetCustomersByCity("New York");

                foreach (var customer in customers)
                {
   
                    Console.WriteLine($"Customer ID: {customer.Id}, Name: {customer.Name}, City: {customer.City}");
                }
            }

            Console.ReadLine();
        }
    }
}

在这个示例中,我们首先定义了一个Customer实体类和一个数据库上下文类MyDbContext。在OnModelCreating方法中,我们将存储过程映射到Customer实体。然后,我们创建了一个CustomerService类,用于调用存储过程并返回结果。在Main方法中,我们创建了数据库上下文和CustomerService实例,并调用GetCustomersByCity方法来获取特定城市的客户列表。最后,我们遍历结果并输出客户信息。

相关文章
|
4天前
|
存储 SQL 数据库
存储过程定义
存储过程是一组为了完成特定功能的SQL语句集合。 存储过程在使用过程中是将常用或者复杂的工作,预先使用SQL语句写好并用一个指定的名称存储起来,这个过程经编译和优化后存储在数据库服务器中。当需要使用该存储过程时,只需要调用它即可。存储过程在执行上比传统SQL速度更快、执行效率更高。
|
3月前
|
人工智能 开发者 前端开发
【创新·未来】当AI遇见代码:Vaadin Copilot引领Web开发新时代,你准备好了吗?
【8月更文挑战第31天】Vaadin 是一个成熟的 Java Web 应用框架,最新版本 24.4.0 带来了多项更新,包括引入 Vaadin Copilot——一个集成 AI 的开发工具,可实现拖放组件、实时更新源代码等功能。此外,Vaadin 24.4.0 还统一了 Hilla 框架,支持 Flow 和 Hilla 视图混合应用,实现 React 组件与 Java 应用的无缝集成。未来,Vaadin 将继续提升开发者体验和应用性能,整合更多现代 Web 技术,如 Web 组件和 PWA 支持,保持其在企业级应用开发领域的领先地位。
57 0
|
5月前
|
存储 SQL 关系型数据库
MySQL数据库——存储过程-变量(系统变量、用户定义变量、局部变量)
MySQL数据库——存储过程-变量(系统变量、用户定义变量、局部变量)
340 0
|
6月前
|
存储 SQL 定位技术
数据库基础(六):T-SQL语言程序设计、游标定义与使用及存储过程创建与信息查找
数据库基础(六):T-SQL语言程序设计、游标定义与使用及存储过程创建与信息查找
105 1