在同一个 Blazor 应用中结合 ADO.NET、EF Core 和 Dapper

介绍

我们将了解如何将 ADO.NET、EF Core 和 Dapper 与 Blazor 应用程序结合使用。我在同一个 Blazor 应用程序中结合了这三种不同的方法。这样,人们就可以从一个地方了解这些不同的方法。

ADO.NET 提供对数据源(例如 SQL Server 和 XML)以及通过 OLE DB 和 ODBC 公开的数据源的一致访问。数据共享消费者应用程序可以使用 ADO.NET 连接到这些数据源并检索、处理和更新它们包含的数据。

Entity Framework 是 Microsoft 支持的 .NET 应用程序开源 ORM 框架。它使开发人员能够使用特定于域的类的对象来处理数据,而无需关注存储这些数据的底层数据库表和列。借助 Entity Framework,开发人员可以在处理数据时以更高的抽象级别工作,并且与传统应用程序相比,可以使用更少的代码来创建和维护面向数据的应用程序。

Dapper 是一个微型 ORM(对象关系映射器),可帮助将本机查询输出映射到域类。它是由 StackOverflow 团队构建并作为开源发布的高性能数据访问系统。如果您的项目更喜欢编写存储过程或编写原始 SQL 查询,而不是使用 EntityFramework 等成熟的 ORM 工具,那么 Dapper 是您的更好选择。使用 Dapper,可以非常轻松地对数据库执行 SQL 查询并将结果映射到 C# 域类。

我们将在 Visual Studio 中创建一个 Blazor 应用程序,并为 ADO.NET、EF Core 和 Dapper 创建三种不同的服务。我们将对所有这些服务使用单一接口。我们将在 Startup 类中逐一注册这些服务,并将它们注入到 Razor 组件中。我们将为 CRUD 操作创建四个 Razor 组件。通过在 Startup 类中注册,我们可以查看 ADO.NET、EF Core 和 Dapper 的所有 CRUD 操作。我们将创建一个简单的员工应用程序来查看这些操作。我将逐步解释所有操作。

在 SQL Server 中创建数据库和表

使用下面的 SQL 脚本创建一个新的数据库和表。

USE master

CREATE DATABASE SarathlalDb;

GO

USE SarathlalDb

CREATE TABLE [dbo].[Employees] (
    [Id]          NVARCHAR (250) NOT NULL,
    [Name]        NVARCHAR (250) NULL,
    [Department]  NVARCHAR (250) NULL,
    [Designation] NVARCHAR (250) NULL,
    [Company]     NVARCHAR (250) NULL,
    [City]        NVARCHAR (250) NULL,
    CONSTRAINT [PK_Employees] PRIMARY KEY CLUSTERED ([Id] ASC)
);

GO

在 Visual Studi 中创建 Blazor 应用程序

从 Visual Studio 中选择 Blazor 模板并创建 Blazor 应用程序。


我们必须在我们的项目中安装以下库。

  • “Microsoft.Data.SqlClient”,
  • “Microsoft.EntityFrameworkCore.SqlServer” and
  • “Dapper”
    我们可以创建一个具有以下属性的“Employee”模型类。我们将在“Data”文件夹中创建所有 C# 类和服务。

Employee.cs

namespace BlazorAdoNetEFCoreDapper.Data
{
    public class Employee
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Department { get; set; }
        public string Designation { get; set; }
        public string Company { get; set; }
        public string City { get; set; }
    }
}

我们可以为 ADO.NET 创建一个“EmployeeAdoNetService”服务类并实现该接口。

EmployeeAdoNetService.cs

using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;

namespace BlazorAdoNetEFCoreDapper.Data
{
    public class EmployeeAdoNetService : IEmployeeService
    {
        private readonly SqlConnectionConfiguration _configuration;
        public EmployeeAdoNetService(SqlConnectionConfiguration configuration)
        {
            _configuration = configuration;
        }
        public async Task<bool> CreateEmployee(Employee employee)
        {
            using (SqlConnection con = new SqlConnection(_configuration.Value))
            {
                const string query = "insert into dbo.Employees (Id,Name,Department,Designation,Company,City) values(@Id,@Name,@Department,@Designation,@Company,@City)";
                SqlCommand cmd = new SqlCommand(query, con)
                {
                    CommandType = CommandType.Text,
                };

                cmd.Parameters.AddWithValue("@Id", Guid.NewGuid().ToString());
                cmd.Parameters.AddWithValue("@Name", employee.Name);
                cmd.Parameters.AddWithValue("@Department", employee.Department);
                cmd.Parameters.AddWithValue("@Designation", employee.Designation);
                cmd.Parameters.AddWithValue("@Company", employee.Company);
                cmd.Parameters.AddWithValue("@City", employee.City);

                con.Open();
                await cmd.ExecuteNonQueryAsync();

                con.Close();
                cmd.Dispose();
            }
            return true;
        }

        public async Task<bool> DeleteEmployee(string id)
        {
            using (SqlConnection con = new SqlConnection(_configuration.Value))
            {
                const string query = "delete dbo.Employees where Id=@Id";
                SqlCommand cmd = new SqlCommand(query, con)
                {
                    CommandType = CommandType.Text,
                };

                cmd.Parameters.AddWithValue("@Id", id);

                con.Open();
                await cmd.ExecuteNonQueryAsync();

                con.Close();
                cmd.Dispose();
            }
            return true;
        }

        public async Task<bool> EditEmployee(string id, Employee employee)
        {
            using (SqlConnection con = new SqlConnection(_configuration.Value))
            {
                const string query = "update dbo.Employees set Name = @Name, Department = @Department, Designation = @Designation, Company = @Company, City = @City where Id=@Id";
                SqlCommand cmd = new SqlCommand(query, con)
                {
                    CommandType = CommandType.Text,
                };

                cmd.Parameters.AddWithValue("@Id", id);
                cmd.Parameters.AddWithValue("@Name", employee.Name);
                cmd.Parameters.AddWithValue("@Department", employee.Department);
                cmd.Parameters.AddWithValue("@Designation", employee.Designation);
                cmd.Parameters.AddWithValue("@Company", employee.Company);
                cmd.Parameters.AddWithValue("@City", employee.City);

                con.Open();
                await cmd.ExecuteNonQueryAsync();

                con.Close();
                cmd.Dispose();
            }
            return true;
        }

        public async Task<List<Employee>> GetEmployees()
        {
            List<Employee> employees = new List<Employee>();

            using (SqlConnection con = new SqlConnection(_configuration.Value))
            {
                const string query = "select * from dbo.Employees";
                SqlCommand cmd = new SqlCommand(query, con)
                {
                    CommandType = CommandType.Text
                };

                con.Open();
                SqlDataReader rdr = await cmd.ExecuteReaderAsync();

                while (rdr.Read())
                {
                    Employee employee = new Employee
                    {
                        Id = rdr["Id"].ToString(),
                        Name = rdr["Name"].ToString(),
                        Department = rdr["Department"].ToString(),
                        Designation = rdr["Designation"].ToString(),
                        Company = rdr["Company"].ToString(),
                        City = rdr["City"].ToString()
                    };
                    employees.Add(employee);
                }
                con.Close();
                cmd.Dispose();
            }
            return employees;
        }

        public async Task<Employee> SingleEmployee(string id)
        {
            Employee employee = new Employee();

            using (SqlConnection con = new SqlConnection(_configuration.Value))
            {
                const string query = "select * from dbo.Employees where Id = @Id";
                SqlCommand cmd = new SqlCommand(query, con)
                {
                    CommandType = CommandType.Text,
                };

                cmd.Parameters.AddWithValue("@Id", id);
                con.Open();
                SqlDataReader rdr = await cmd.ExecuteReaderAsync();

                if (rdr.Read())
                {

                    employee.Id = rdr["Id"].ToString();
                    employee.Name = rdr["Name"].ToString();
                    employee.Department = rdr["Department"].ToString();
                    employee.Designation = rdr["Designation"].ToString();
                    employee.Company = rdr["Company"].ToString();
                    employee.City = rdr["City"].ToString();
                }
                con.Close();
                cmd.Dispose();
            }
            return employee;
        }
    }
}

我们需要一个“SqlDbContext”数据库上下文类来进行 EF Core 操作。

SqlDbContext.cs

using Microsoft.EntityFrameworkCore;

namespace BlazorAdoNetEFCoreDapper.Data
{
    public class SqlDbContext : DbContext
    {
        public SqlDbContext(DbContextOptions<SqlDbContext> options)
           : base(options)
        {
        }
        public DbSet<Employee> Employees { get; set; }
    }
}

我们继承了上述类中的 DbContext 类,并为 SQL 数据库中的 Employees 表定义了一个 DB 设置属性。

我们可以创建一个“EmployeeEfService”服务类用于实体框架操作。

EmployeeEfService.

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

namespace BlazorAdoNetEFCoreDapper.Data
{
    public class EmployeeEfService : IEmployeeService
    {
        private readonly SqlDbContext _dbContext;

        public EmployeeEfService(SqlDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public async Task<List<Employee>> GetEmployees()
        {
            return await _dbContext.Employees.ToListAsync();
        }

        public async Task<bool> CreateEmployee(Employee employee)
        {
            employee.Id = Guid.NewGuid().ToString();
            _dbContext.Add(employee);
            try
            {
                await _dbContext.SaveChangesAsync();
                return true;
            }
            catch (DbUpdateException)
            {
                return false;
            }

        }

        public async Task<Employee> SingleEmployee(string id)
        {
            return await _dbContext.Employees.FindAsync(id);
        }

        public async Task<bool> EditEmployee(string id, Employee employee)
        {
            if (id != employee.Id)
            {
                return false;
            }

            _dbContext.Entry(employee).State = EntityState.Modified;
            await _dbContext.SaveChangesAsync();
            return true;
        }

        public async Task<bool> DeleteEmployee(string id)
        {
            var employee = await _dbContext.Employees.FindAsync(id);
            if (employee == null)
            {
                return false;
            }

            _dbContext.Employees.Remove(employee);
            await _dbContext.SaveChangesAsync();
            return true;
        }
    }
}

我们在上面的服务类中定义了 EF Core 的所有逻辑。

我们可以创建一个“EmployeeDapperService”服务类,用于dapper操作。

EmployeeDapperService.cs

using Dapper;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace BlazorAdoNetEFCoreDapper.Data
{
    public class EmployeeDapperService : IEmployeeService
    {
        private readonly SqlConnectionConfiguration _configuration;

        public EmployeeDapperService(SqlConnectionConfiguration configuration)
        {
            _configuration = configuration;
        }

        public async Task<bool> CreateEmployee(Employee employee)
        {
            using (var conn = new SqlConnection(_configuration.Value))
            {
                const string query = @"insert into dbo.Employees (Id,Name,Department,Designation,Company,City) values(@Id,@Name,@Department,@Designation,@Company,@City)";
                conn.Open();
                try
                {
                    await conn.ExecuteAsync(query, new { Id = Guid.NewGuid().ToString(), employee.Name, employee.Department, employee.Designation, employee.Company, employee.City }, commandType: CommandType.Text);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    conn.Close();
                }
            }
            return true;
        }

        public async Task<bool> DeleteEmployee(string id)
        {
            using (var conn = new SqlConnection(_configuration.Value))
            {
                const string query = @"delete dbo.Employees where Id=@Id";
                conn.Open();
                try
                {
                    await conn.ExecuteAsync(query, new { id }, commandType: CommandType.Text);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    conn.Close();
                }
            }
            return true;
        }

        public async Task<bool> EditEmployee(string id, Employee employee)
        {
            using (var conn = new SqlConnection(_configuration.Value))
            {
                const string query = @"update dbo.Employees set Name = @Name, Department = @Department, Designation = @Designation, Company = @Company, City = @City where Id=@Id";
                conn.Open();
                try
                {
                    await conn.ExecuteAsync(query, new { employee.Name, employee.Department, employee.Designation, employee.Company, employee.City, id }, commandType: CommandType.Text);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    conn.Close();
                }
            }
            return true;
        }

        public async Task<List<Employee>> GetEmployees()
        {
            IEnumerable<Employee> employees;
            using (var conn = new SqlConnection(_configuration.Value))
            {
                const string query = @"select * from dbo.Employees";

                conn.Open();
                try
                {
                    employees = await conn.QueryAsync<Employee>(query, commandType: CommandType.Text);

                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    conn.Close();
                }

            }
            return employees.ToList();
        }

        public async Task<Employee> SingleEmployee(string id)
        {
            Employee employee = new Employee();
            using (var conn = new SqlConnection(_configuration.Value))
            {
                const string query = @"select * from dbo.Employees where Id=@Id";

                conn.Open();
                try
                {
                    employee = await conn.QueryFirstOrDefaultAsync<Employee>(query, new { id }, commandType: CommandType.Text);

                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    conn.Close();
                }

            }
            return employee;
        }
    }
}

我们可以在 Startup 类中注册 SQL 连接配置和实体框架 DB 上下文

Startup 类中的 ConfigureServices 方法。

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddSingleton<WeatherForecastService>();

    services.AddDbContext<SqlDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("SqlDbContext")));

    var sqlConnectionConfiguration = new SqlConnectionConfiguration(Configuration.GetConnectionString("SqlDbContext"));
    services.AddSingleton(sqlConnectionConfiguration);

    services.AddServerSideBlazor(o => o.DetailedErrors = true);
}

我们可以在“Pages”文件夹中创建四个用于 CRUD 操作的 Razor 组件

ListEmployees.razor

@using BlazorAdoNetEFCoreDapper.Data

@page "/listemployees"
@inject IEmployeeService EmployeeService

<h2>Employee Details</h2>
<p>
    <a href="/addemployee">Create New Employee</a>
</p>
@if (employees == null)
{
    <img src="./basicloader.gif" />
}
else
{
    <table class='table'>
        <thead>
            <tr>
                <th>Name</th>
                <th>Department</th>
                <th>Designation</th>
                <th>Company</th>
                <th>City</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var employee in employees)
            {
                <tr>
                    <td>@employee.Name</td>
                    <td>@employee.Department</td>
                    <td>@employee.Designation</td>
                    <td>@employee.Company</td>
                    <td>@employee.City</td>
                    <td>
                        <a href='/editemployee/@employee.Id'>Edit</a>
                        <a href='/deleteemployee/@employee.Id'>Delete</a>
                    </td>
                </tr>

            }
        </tbody>
    </table>
}

@code {
    List<Employee> employees;

    protected override async Task OnInitializedAsync()
    {
        employees = await EmployeeService.GetEmployees();
    }
}

AddEmployee.razor

@using BlazorAdoNetEFCoreDapper.Data

@page "/addemployee"
@inject NavigationManager NavigationManager
@inject IEmployeeService EmployeeService

<h2>Create Employee</h2>
<hr />
<form>
    <div class="row">
        <div class="col-md-8">
            <div class="form-group">
                <label for="Name" class="control-label">Name</label>
                <input for="Name" class="form-control" @bind="@employee.Name" />
            </div>
            <div class="form-group">
                <label for="Department" class="control-label">Department</label>
                <input for="Department" class="form-control" @bind="@employee.Department" />
            </div>
            <div class="form-group">
                <label for="Designation" class="control-label">Designation</label>
                <input for="Designation" class="form-control" @bind="@employee.Designation" />
            </div>
            <div class="form-group">
                <label for="Company" class="control-label">Company</label>
                <input for="Company" class="form-control" @bind="@employee.Company" />
            </div>
            <div class="form-group">
                <label for="City" class="control-label">City</label>
                <input for="City" class="form-control" @bind="@employee.City" />
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4">
            <div class="form-group">
                <input type="button" class="btn btn-primary" @onclick="@CreateEmployee" value="Save" />
                <input type="button" class="btn" @onclick="@Cancel" value="Cancel" />
            </div>
        </div>
    </div>
</form>

@code {

    Employee employee = new Employee();

    protected async Task CreateEmployee()
    {
        await EmployeeService.CreateEmployee(employee);
        NavigationManager.NavigateTo("listemployees");
    }

    void Cancel()
    {
        NavigationManager.NavigateTo("listemployees");
    }
}

EditEmployee.razor

@using BlazorAdoNetEFCoreDapper.Data

@page "/editemployee/{id}"
@inject NavigationManager NavigationManager
@inject IEmployeeService EmployeeService

<h2>Edit Employee</h2>
<hr />
<form>
    <div class="row">
        <div class="col-md-8">
            <div class="form-group">
                <label for="Name" class="control-label">Name</label>
                <input for="Name" class="form-control" @bind="@employee.Name" />
            </div>
            <div class="form-group">
                <label for="Department" class="control-label">Department</label>
                <input for="Department" class="form-control" @bind="@employee.Department" />
            </div>
            <div class="form-group">
                <label for="Designation" class="control-label">Designation</label>
                <input for="Designation" class="form-control" @bind="@employee.Designation" />
            </div>
            <div class="form-group">
                <label for="Company" class="control-label">Company</label>
                <input for="Company" class="form-control" @bind="@employee.Company" />
            </div>
            <div class="form-group">
                <label for="City" class="control-label">City</label>
                <input for="City" class="form-control" @bind="@employee.City" />
            </div>
        </div>
    </div>
    <div class="row">
        <div class="form-group">
            <input type="button" class="btn btn-primary" @onclick="@UpdateEmployee" value="Update" />
            <input type="button" class="btn" @onclick="@Cancel" value="Cancel" />
        </div>
    </div>
</form>

@code {

    [Parameter]
    public string id { get; set; }

    Employee employee = new Employee();

    protected override async Task OnInitializedAsync()
    {
        employee = await EmployeeService.SingleEmployee(id);
    }

    protected async Task UpdateEmployee()
    {
        await EmployeeService.EditEmployee(id, employee);
        NavigationManager.NavigateTo("listemployees");
    }

    void Cancel()
    {
        NavigationManager.NavigateTo("listemployees");
    }
}

DeleteEmployee.razor

@using BlazorAdoNetEFCoreDapper.Data

@page "/deleteemployee/{id}"
@inject NavigationManager NavigationManager
@inject IEmployeeService EmployeeService

<h2>Confirm Delete</h2>
<p>Are you sure you want to delete this Employee with Id : <b>@id</b></p>
<br />
<div class="col-md-4">
    <table class="table">
        <tr>
            <td>Name</td>
            <td>@employee.Name</td>
        </tr>
        <tr>
            <td>Department</td>
            <td>@employee.Department</td>
        </tr>
        <tr>
            <td>Designation</td>
            <td>@employee.Designation</td>
        </tr>
        <tr>
            <td>Company</td>
            <td>@employee.Company</td>
        </tr>
        <tr>
            <td>City</td>
            <td>@employee.City</td>
        </tr>
    </table>
    <div class="form-group">
        <input type="button" value="Delete" @onclick="@Delete" class="btn btn-primary" />
        <input type="button" value="Cancel" @onclick="@Cancel" class="btn" />
    </div>
</div>

@code {

    [Parameter]
    public string id { get; set; }
    Employee employee = new Employee();

    protected override async Task OnInitializedAsync()
    {
        employee = await EmployeeService.SingleEmployee(id);
    }

    protected async Task Delete()
    {
        await EmployeeService.DeleteEmployee(id);
        NavigationManager.NavigateTo("listemployees");
    }

    void Cancel()
    {
        NavigationManager.NavigateTo("listemployees");
    }
}

我们可以修改 NavMenu 共享组件来添加员工列表页面的导航。

NavMenu.razor

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">ADO.NET, EF & Dapper</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="listemployees">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Employee data
            </NavLink>
        </li>
    </ul>
</div>

@code {
    bool collapseNavMenu = true;

    string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

我们可以在 Startup 类中使用 IEmployeeService 接口注册 ADO.NET 服务。

我们可以运行该应用程序。

单击员工数据菜单链接并创建新的员工数据。

保存数据后,数据将出现在员工列表页面。您可以点击“编辑”超链接来编辑数据。

我们可以在 Startup 类中使用“EmployeeEfService”而不是 EmployeeAdoNetService 注册 IEmployeeService 接口。通过这个简单的更改,整个应用程序将适用于实体框架。这是依赖注入的主要优势。

我们可以再次运行该应用程序并添加/编辑员工数据。您可以注意到,应用程序正在按预期运行。

我们可以在Startup类中使用“EmployeeDapperService”注册IEmployeeService接口。

再次,我们可以运行应用程序并添加/编辑员工数据。您也可以对 Dapper 执行所有 CRUD 操作。

结论

在这篇文章中,我们了解了如何使用 ADO.NET、EF Core 和 Dapper 将 Blazor 应用程序与 SQL Server 连接起来。我们为三种不同的服务创建了一个接口,并逐一在 Startup 类中注册。我们使用这三种不同的方法创建和编辑了员工数据。我相信,通过这篇文章,您都能很好地理解 ADO.NET、EF Core 和 Dapper。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谢.锋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值