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

C#中从数据库获取的多类别项目集合的最优分类实现方案问询

在C#中对数据库获取的多组项目分类的最优方案

嘿,先看看你当前实现里的几个小问题,咱们一步步优化成更优雅、可维护的方案:

当前实现的问题

  • 重复代码冗余:Fruits和Bakery类逻辑几乎完全一致,只是分类ID不同,后续新增分类要重复写大量代码,维护成本很高
  • 硬编码&低级错误:Fruits类里的查询居然用了(int)IdOfCategory.Bakery,这明显是笔误;而且直接把分类ID写在查询里,既不安全也不灵活
  • 职责混乱:实体类(比如Fruits)居然直接承担数据库操作,违反了单一职责原则,类的职责不清晰

最优实现方案

我们可以通过抽象通用逻辑、单一职责拆分和灵活的数据获取策略来优化,具体步骤如下:

1. 定义通用的Product实体类

先把数据库的Product表映射成一个纯数据类,只负责存储产品信息:

public class Product
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public string ProductDescription { get; set; }
    public int CategoryId { get; set; }
}

2. 规范分类枚举(保持语义清晰)

调整枚举命名更符合C#规范,后续新增分类直接加在这里就行:

public enum CategoryId
{
    Fruits = 1,
    Bakery = 2
}

3. 抽象数据访问层(Repository模式)

把所有数据库操作集中到一个类里,避免重复代码,同时使用参数化查询防止SQL注入:

public class ProductRepository
{
    // 把连接字符串抽出来,方便后续配置(比如移到appsettings.json)
    private readonly string _connectionString = @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\user\Documents\mario.mdf;Integrated Security=True;Connect Timeout=30";

    /// <summary>
    /// 根据分类ID获取对应产品(适合只需要单个分类数据的场景)
    /// </summary>
    public List<Product> GetProductsByCategory(CategoryId categoryId)
    {
        var products = new List<Product>();
        // 参数化查询,避免SQL注入,同时更灵活
        string query = @"SELECT ProductId, ProductName, ProductDescription, CategoryId 
                         FROM Products 
                         WHERE CategoryId = @CategoryId";

        using (SqlConnection connection = new SqlConnection(_connectionString))
        using (SqlCommand command = new SqlCommand(query, connection))
        {
            command.Parameters.AddWithValue("@CategoryId", (int)categoryId);
            connection.Open();

            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    products.Add(MapReaderToProduct(reader));
                }
            }
        }
        return products;
    }

    /// <summary>
    /// 一次性获取所有产品并按分类分组(适合需要多个分类数据的场景,减少数据库连接次数)
    /// </summary>
    public Dictionary<CategoryId, List<Product>> GetAllProductsGroupedByCategory()
    {
        var allProducts = new List<Product>();
        string query = @"SELECT ProductId, ProductName, ProductDescription, CategoryId 
                         FROM Products";

        using (SqlConnection connection = new SqlConnection(_connectionString))
        using (SqlCommand command = new SqlCommand(query, connection))
        {
            connection.Open();
            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    allProducts.Add(MapReaderToProduct(reader));
                }
            }
        }

        // 用LINQ快速完成分组,代码简洁高效
        return allProducts.GroupBy(p => (CategoryId)p.CategoryId)
                          .ToDictionary(group => group.Key, group => group.ToList());
    }

    // 抽取出Reader到Product的映射逻辑,避免重复代码
    private Product MapReaderToProduct(SqlDataReader reader)
    {
        return new Product
        {
            ProductId = reader.GetInt32(0),
            ProductName = reader.GetString(1),
            // 处理可能的空值,避免抛出异常
            ProductDescription = reader.IsDBNull(2) ? null : reader.GetString(2),
            CategoryId = reader.GetInt32(3)
        };
    }
}

4. 使用示例

现在你可以根据需求选择不同的获取方式:

// 场景1:只需要某一个分类的产品
var productRepo = new ProductRepository();
var fruits = productRepo.GetProductsByCategory(CategoryId.Fruits);
var bakeryItems = productRepo.GetProductsByCategory(CategoryId.Bakery);

// 场景2:需要多个分类的产品,一次性获取再分组更高效
var groupedProducts = productRepo.GetAllProductsGroupedByCategory();
var fruitsFromGroup = groupedProducts[CategoryId.Fruits];
var bakeryFromGroup = groupedProducts[CategoryId.Bakery];

优化后的优势

  • 单一职责:数据操作集中在Repository,实体类只负责存储数据,代码结构清晰
  • 可维护性:新增分类只需要在枚举里加值,不用写新的类和重复的查询逻辑
  • 安全性:参数化查询彻底避免SQL注入风险
  • 灵活性:两种获取策略可选,根据数据量和需求选择最优方式
  • 可读性:代码结构清晰,命名规范,后续接手的人能快速理解

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 21:22:44