You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C# ASP.NET中为控制器注入SQLite连接与仓储实例

配置ASP.NET Core依赖注入实现仓储模式与SQLite连接

我正在开发一个使用SQLite数据库的简单应用,采用仓储模式处理所有数据库操作。已编写依赖AddressRepository的AddressController,以及依赖SqliteConnection的AddressRepository实现,但不知如何配置使控制器能获取仓储实例,相关代码如下:

控制器代码

using Microsoft.AspNetCore.Mvc;
using WebApplication2.Models;
using WebApplication2.Data;

namespace WebApplication2.Controllers
{
    [ApiController]
    public class AddressController : Controller
    {
        private readonly AddressRepository _addressReposity;
        public AddressController(AddressRepository addressRepository)
        {
            _addressReposity = addressRepository;
        }

        [HttpGet("/addresses")]
        [ProducesResponseType(200, Type = typeof(List<(int, Address)>))]
        public IActionResult getAddresses(Address address, bool orderByAscending)
        {
            List<(int, Address)> addresses = _addressReposity.getAddresses(address, orderByAscending);

            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            return Ok(addresses);
        }

        [HttpPost("/addresses")]
        [ValidateAntiForgeryToken]
        public IActionResult addAddress(Address address)
        { 
            return View();
        }

        [HttpGet("/addresses/{id}")]
        [ProducesResponseType(200, Type = typeof(Address))]
        public IActionResult getSingleAddress(int id) 
        {
            if(!_addressReposity.existAddress(id))
                return BadRequest(ModelState);

            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            return Ok(_addressReposity.getSingleAddress(id));
        }
        [HttpPut("/addresses/{id}")]
        public IActionResult updateAddress(Address address, int id) 
        {
            if (!_addressReposity.existAddress(id))
                return BadRequest(ModelState);

            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            _addressReposity.UpdateAddress(address, id);

            return Ok();
        }

        [HttpDelete("/addresses/{id}")]
        public IActionResult deleteAddress(int id) 
        {
            if (!_addressReposity.existAddress(id))
                return BadRequest(ModelState);

            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            return Ok();

        }
    }
}

仓储代码

using System.Data;
using WebApplication2.Models;
using Microsoft.Data.Sqlite;

namespace WebApplication2.Data
{
    public class AddressRepository : IAddressRepository
    {
        private readonly SqliteConnection _db_connection;
        public AddressRepository(SqliteConnection db_connection) 
        {
            _db_connection = db_connection;
        }
        public List<(int, Address)> readerToAddresses(SqliteDataReader reader)
        {
            List<(int, Address)> addresses = new List<(int, Address)>();
            while (reader.Read())
            {
                int ID = reader.GetInt32("ID");
                string street =  reader[2].ToString();
                string city   =  reader[3].ToString();
                string zipcode = reader[4].ToString();
                int houseNumber = (int)reader[5];
                string addition;
                if (reader[6] == null)
                    addition = null;
                else
                    addition = reader[6].ToString();
                addresses.Append((ID, new Address(street, city, zipcode, houseNumber)));

            }
            return addresses;
        }

        public string getSearchAddressesString(string start, Address search_info)
        {
            string search_command_string = start;
            if (search_info != null)
            {
                foreach (var prop in search_info.GetType().GetProperties())
                {
                    if (prop.GetValue(search_info) != null)
                    {
                        if (prop.PropertyType.Name == "String")
                        {
                            search_command_string += prop.Name.ToString() + " = '" + prop.GetValue(search_info).ToString() + "'" + ", ";
                        }
                        else if (prop.PropertyType.Name == "Int32")
                        {
                            search_command_string += prop.Name.ToString() + " = " + ((int)prop.GetValue(search_info)).ToString() + ", ";
                        }
                    }
                }
            }
            return search_command_string;
        }
        public List<(int, Address)> getAddresses(Address search_info, bool orderByAscending)
        {
            string search_command_string = $"SELECT * FROM ADDRESSES WHERE ";

            search_command_string = getSearchAddressesString(search_command_string, search_info);

            if (search_command_string == "SELECT * FROM ADDRESSES WHERE ")
                search_command_string = "SELECT * FROM ADDRESSES";

            SqliteCommand search_command = new SqliteCommand(search_command_string, _db_connection);
            SqliteDataReader reader = search_command.ExecuteReader();
            return readerToAddresses(reader);
        }
        public void InsertAddress(Address address)
        {
            string insert_command_string_part_one = "INSERT INTO ADDRESSES (";
            string insert_command_string_part_two = "VALUES(";
            if (address != null)
            {
                foreach (var prop in address.GetType().GetProperties())
                {
                    insert_command_string_part_one += prop.Name.ToString() + ", ";
                    if (prop.GetValue(address) != null)
                    {
                        if (prop.PropertyType.Name == "String")
                        {
                            insert_command_string_part_two += "'" + prop.GetValue(address).ToString() + "'" + ", "; 
                        }
                        else if (prop.PropertyType.Name == "Int32")
                        {
                            insert_command_string_part_two += ((int)prop.GetValue(address)).ToString() + ", ";
                        }
                    }
                }
            }
            insert_command_string_part_one = insert_command_string_part_one.Substring(0, insert_command_string_part_one.Length - 2) + ") ";
            insert_command_string_part_two = insert_command_string_part_two.Substring(0, insert_command_string_part_two.Length - 2) + ')';
            SqliteCommand insert_command = new SqliteCommand(insert_command_string_part_one + insert_command_string_part_two, _db_connection);
            insert_command.ExecuteNonQuery();
        }

        public void UpdateAddress(Address address, int id)
        {
            bool not_all_null = false;
            string update_command_string = "UPDATE ADDRESSES SET ";
            if (address != null)
            {
                foreach (var prop in address.GetType().GetProperties())
                {
                    if (prop.GetValue(address) != null)
                    {
                        not_all_null = true;
                        if (prop.PropertyType.Name == "String")
                        {
                            update_command_string += prop.Name.ToString() + " = '" + prop.GetValue(address).ToString() + "'" + ", ";
                        }
                        else if (prop.PropertyType.Name == "Int32")
                        {
                            update_command_string += prop.Name.ToString() + " = " + ((int)prop.GetValue(address)).ToString() + ", ";
                        }
                    }
                }
                if (not_all_null) 
                {
                    update_command_string = update_command_string.Substring(0, update_command_string.Length - 2) + $" WHERE ID = {(int)id}";
                    SqliteCommand update_command = new SqliteCommand(update_command_string, _db_connection);
                    update_command.ExecuteNonQuery();
                }
            }
        }

        public void DeleteAddress(int id)
        {
            string delete_command_string = $"DELETE FROM ADDRESSES WHERE ID = {(int)id}";
            SqliteCommand delete_command = new SqliteCommand(delete_command_string, _db_connection);
            delete_command.ExecuteNonQuery();
        }

        public bool existAddress(int id)
        {
            string exists_command_string = $"SELECT * FROM ADDRESSES WHERE ID={id}";
            SqliteCommand exists_command = new SqliteCommand(exists_command_string, _db_connection);
            SqliteDataReader reader = exists_command.ExecuteReader();

            while (reader.Read())
                return true;

            return false;
        }

        public Address getSingleAddress(int id)
        {
            string get_address_string = $"SELECT * FROM ADDRESSES WHERE ID={id}";
            SqliteCommand single_address_command = new SqliteCommand(get_address_string, _db_connection);
            SqliteDataReader reader = single_address_command.ExecuteReader();
            return readerToAddresses(reader)[0].Item2;
        }
    }
}

appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": "Addresses.sqlite"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

配置步骤指引

1. 在Program.cs注册依赖注入服务

ASP.NET Core通过依赖注入容器管理实例,需要将SqliteConnection和仓储类/接口注册到容器中:

var builder = WebApplication.CreateBuilder(args);

// 添加控制器服务
builder.Services.AddControllers();

// 注册SqliteConnection:作用域生命周期,每个请求一个实例
builder.Services.AddScoped<SqliteConnection>(sp => 
{
    var connStr = builder.Configuration.GetConnectionString("DefaultConnection");
    var connection = new SqliteConnection($"Data Source={connStr}");
    connection.Open();
    return connection;
});

// 注册仓储:推荐面向接口注册,提升可测试性和扩展性
builder.Services.AddScoped<IAddressRepository, AddressRepository>();

var app = builder.Build();

// 中间件配置
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

2. 修改控制器依赖为接口(可选但推荐)

将控制器对AddressRepository的依赖改为IAddressRepository,符合依赖倒置原则:

private readonly IAddressRepository _addressReposity;
public AddressController(IAddressRepository addressRepository)
{
    _addressReposity = addressRepository;
}

3. 修复SQL注入风险(必须)

当前仓储直接拼接SQL字符串,存在严重安全漏洞,全部改为参数化查询。示例修改getAddresses方法:

public List<(int, Address)> getAddresses(Address search_info, bool orderByAscending)
{
    var addresses = new List<(int, Address)>();
    var sqlBuilder = new StringBuilder("SELECT * FROM ADDRESSES");
    var parameters = new List<SqliteParameter>();

    if (search_info != null)
    {
        var conditions = new List<string>();
        foreach (var prop in search_info.GetType().GetProperties())
        {
            var value = prop.GetValue(search_info);
            if (value != null)
            {
                conditions.Add($"{prop.Name} = @{prop.Name}");
                parameters.Add(new SqliteParameter($"@{prop.Name}", value));
            }
        }

        if (conditions.Any())
        {
            sqlBuilder.Append(" WHERE ").Append(string.Join(" AND ", conditions));
        }
    }

    // 添加排序逻辑
    sqlBuilder.Append(orderByAscending ? " ORDER BY ID ASC" : " ORDER BY ID DESC");

    using var command = new SqliteCommand(sqlBuilder.ToString(), _db_connection);
    command.Parameters.AddRange(parameters.ToArray());
    
    using var reader = command.ExecuteReader();
    while (reader.Read())
    {
        int ID = reader.GetInt32("ID");
        string street = reader["Street"].ToString();
        string city = reader["City"].ToString();
        string zipcode = reader["Zipcode"].ToString();
        int houseNumber = reader.GetInt32("HouseNumber");
        string addition = reader.IsDBNull(reader.GetOrdinal("Addition")) ? null : reader["Addition"].ToString();
        
        addresses.Add((ID, new Address(street, city, zipcode, houseNumber, addition)));
    }

    return addresses;
}

其他增删改方法需参照此逻辑修改,彻底消除SQL注入风险。

4. 初始化SQLite数据库表

确保启动时自动创建ADDRESSES表,在Program.cs中添加:

// 初始化数据库表
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    var connection = services.GetRequiredService<SqliteConnection>();
    var createTableSql = @"
        CREATE TABLE IF NOT EXISTS ADDRESSES (
            ID INTEGER PRIMARY KEY AUTOINCREMENT,
            Street TEXT NOT NULL,
            City TEXT NOT NULL,
            Zipcode TEXT NOT NULL,
            HouseNumber INTEGER NOT NULL,
            Addition TEXT
        );";
    using var command = new SqliteCommand(createTableSql, connection);
    command.ExecuteNonQuery();
}

内容的提问来源于stack exchange,提问作者berend

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:05:24