在 ASP.NET Boilerplate 中使用存储过程、用户自定义函数和视图的自定义仓库





5.00/5 (10投票s)
如何在 ASP.NET Boilerplate 中创建自定义仓库,并在仓库中使用存储过程、视图和用户自定义函数
目录
从 Github 仓库 获取源码。
引言
在本文中,我将解释如何在 ASP.NET Boilerplate 中创建自定义仓库,并使用存储过程、视图和用户自定义函数。要了解更多关于 ASP.NET Boilerplate 框架的信息,请查看其 文档。
要开始使用 ASP.NET Boilerplate 框架,您可以从 这里 下载一个启动模板。我选择了 ASP.NET Core 和多页 Web 应用程序,项目名称为 Acme.PhoneBook
。如果您需要帮助设置模板,请参阅 此链接。
在 Visual Studio 2017 中打开下载的解决方案后,我们看到如下解决方案结构
创建自定义仓库
我们将创建一个自定义仓库,使用存储过程、视图和用户自定义函数对 User 实体执行一些基本操作。要实现自定义仓库,只需从您的应用程序特定基础仓库类派生即可。
在领域层 (Acme.PhoneBook.Core
) 中实现 interface
。
public interface IUserRepository: IRepository<User, long>
{
...
...
}
在基础设施层 (Acme.PhoneBook.EntityFrameworkCore
) 中实现仓库。
public class UserRepository : PhoneBookRepositoryBase<User, long>, IUserRepository
{
private readonly IActiveTransactionProvider _transactionProvider;
public UserRepository(IDbContextProvider<PhoneBookDbContext> dbContextProvider,
IActiveTransactionProvider transactionProvider)
: base(dbContextProvider)
{
_transactionProvider = transactionProvider;
}
...
...
}
辅助方法 (Helper Methods)
首先,我们创建一些将在其他方法之间共享的辅助方法,以执行一些通用任务
private DbCommand CreateCommand
(string commandText, CommandType commandType, params SqlParameter[] parameters)
{
var command = Context.Database.GetDbConnection().CreateCommand();
command.CommandText = commandText;
command.CommandType = commandType;
command.Transaction = GetActiveTransaction();
foreach (var parameter in parameters)
{
command.Parameters.Add(parameter);
}
return command;
}
private void EnsureConnectionOpen()
{
var connection = Context.Database.GetDbConnection();
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
}
private DbTransaction GetActiveTransaction()
{
return (DbTransaction)_transactionProvider.GetActiveTransaction(new ActiveTransactionProviderArgs
{
{"ContextType", typeof(PhoneBookDbContext) },
{"MultiTenancySide", MultiTenancySide }
});
}
存储过程
这里有一个存储过程调用,用于获取所有用户的用户名。将其添加到仓库实现 (UserRepository
) 中。
public async Task<List<string>> GetUserNames()
{
EnsureConnectionOpen();
using (var command = CreateCommand("GetUsernames", CommandType.storedProcedure))
{
using (var dataReader = await command.ExecuteReaderAsync())
{
var result = new List<string>();
while (dataReader.Read())
{
result.Add(dataReader["UserName"].ToString());
}
return result;
}
}
}
并在 IUserRepository
中定义 GetUserNames
方法
public interface IUserRepository: IRepository<User, long>
{
...
Task<List<string>> GetUserNames();
...
}
这是被调用的存储过程
USE [PhoneBookDb]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[GetUsernames]
AS
BEGIN
SET NOCOUNT ON;
SELECT UserName FROM AbpUsers
END
GO
现在我们实现了从数据库调用存储过程的函数。让我们在应用程序服务中使用它
public class UserAppService : AsyncCrudAppService<User, UserDto,
long, PagedResultRequestDto, CreateUserDto, UserDto>, IUserAppService
{
private readonly IUserRepository _userRepository;
public UserAppService(..., IUserRepository userRepository)
: base(repository)
{
...
_userRepository = userRepository;
}
...
public async Task<List<string>> GetUserNames()
{
return await _userRepository.GetUserNames();
}
}
这里是另一个示例,它将一个参数发送到存储过程以删除用户
public async Task DeleteUser(EntityDto input)
{
await Context.Database.ExecuteSqlCommandAsync(
"EXEC DeleteUserById @id",
default(CancellationToken),
new SqlParameter("id", input.Id)
);}
用于删除调用的存储过程
USE [PhoneBookDb]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[DeleteUserById]
@id int
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM AbpUsers WHERE [Id] = @id
END
GO
还有另一个示例,它将一个参数发送到存储过程以更新用户的电子邮件地址
public async Task UpdateEmail(UpdateEmailDto input)
{
await Context.Database.ExecuteSqlCommandAsync(
"EXEC UpdateEmailById @email, @id",
default(CancellationToken),
new SqlParameter("id", input.Id),
new SqlParameter("email", input.EmailAddress)
);
}
用于 update
方法调用的存储过程
USE [PhoneBookDb]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[UpdateEmailById]
@email nvarchar(256),
@id int
AS
BEGIN
SET NOCOUNT ON;
UPDATE AbpUsers SET [EmailAddress] = @email WHERE [Id] = @id
END
GO
视图
您可以像这样调用视图
public async Task<List<string>> GetAdminUsernames()
{
EnsureConnectionOpen();
using (var command = CreateCommand("SELECT * FROM dbo.UserAdminView", CommandType.Text))
{
using (var dataReader = await command.ExecuteReaderAsync())
{
var result = new List<string>();
while (dataReader.Read())
{
result.Add(dataReader["UserName"].ToString());
}
return result;
}
}
}
此方法的视图
SELECT *
FROM dbo.AbpUsers
WHERE (Name = 'admin')
用户自定义函数
您可以像这样调用用户自定义函数
public async Task<GetUserByIdOutput> GetUserById(EntityDto input)
{
EnsureConnectionOpen();
using (var command = CreateCommand("SELECT dbo.GetUsernameById(@id)",
CommandType.Text, new SqlParameter("@id", input.Id)))
{
var username = (await command.ExecuteScalarAsync()).ToString();
return new GetUserByIdOutput() { Username = username };
}
}
此方法的用户自定义函数
USE [PhoneBookDb]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[GetUsernameById]
@id int
)
RETURNS nvarchar(32)
AS
BEGIN
DECLARE @username nvarchar(32)
SELECT @username = [UserName] FROM AbpUsers WHERE [ID] = @id
RETURN @username
END
GO
Github 上的源码
源码已发布在 github 这里。