如何设计BOM表结构

1,538 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

本文结合自己工作中所使用到的相关ORM为基础进行讲述,可能使用不同的框架或ORM等不同,表结构会有略微不同,不过大致思想都是一样的。

无限层级的BOM

很常见的一种功能需求,但是实现起来着实不是很简单

最初设计

刚开始我直接就上手写了三个表:零件表,主料表、辅料表

/// <summary>
/// 零件
/// </summary>
public class Part
{
    public int Id { get; set; }

    public string Name { get; set; }
}

/// <summary>
/// 主零件表
/// </summary>
public class MainPart 
{
    public int Id { get; set; }
    public Part MPart { get; set; }
}

/// <summary>
/// 辅零件表
/// </summary>
public class SubPart
{
    public int Id { get; set; }

    public int MId { get; set; }

    public Part SPart { get; set; }
}

这个垃圾表设计导致我后面功能逻辑越写越复杂和繁琐....
例如在创建BOM时,首先选定主零件,然后再选择它是由哪些零件组成的,而这些零件还可能有更小的零件组成,用户可能一次会创建多个BOM出来(未加限制,也是一个不成熟的设计)。
用户每添加一个零件进来,我都需要进行判定
(1)首先,先把比他层级高的零件,全部取出来,然后一个一个到数据库中进行比对,是否有重复的(因为B、C零件组成A,那B零件的组成部分就不可能有B、A了,有可能有C...细想),还要比对是否有主辅互引用的(比如数据库中已经有了3个B组成了一个A,那A就是主料,B是辅料,不可能再出现A组成B的反向操作了)。
(2)还需要判定当前零件是否为BOM主料(即数据库中是否有以他为主料的BOM结构),如果有,那还需要把他的辅料循环,向上进行一个判定(即(1)的判定...) 最终判定没问题了,才能把这个零件放进来,若要有删除或编辑操作,又是一大堆的判定操作!
而这些判定,在后端通过For循环套For循环,里面还嵌套递归等操作,关键是还要不停的查数据库表
可我还是实现了完整功能代码,但这个代码的性能可想有多差,怎么敢给客户使用呢!
一次尝试失败而告终
最开始我还沾沾自喜,我的思维逻辑有多缜密,但是...太缺乏经验了

思考后优化

有了那次失败了设计,浪费了一些时间,必须沉下心来思考一下再动手!
从本质上讲,什么主零件,什么辅零件,都是我人为给他下的定义,对于系统来说,都是零件表(Part)中的一条数据!
那就没必要分两张表了,直接一张表,存两者的Id即可,相当于主辅零件关联表

表结构如下:

//Part表同上面代码块中一样,未做改变

public class BOM
{
    public int Id { get; set; }

    /// <summary>
    /// 父零件Id
    /// </summary>
    public int MainId { get; set; }

    /// <summary>
    /// 子零件Id
    /// </summary>
    public int SubId { get; set; }

    /// <summary>
    /// 子零件数量
    /// </summary>
    public int Count { get; set; }
}

突然一下子简单明了很多!
优化还没结束
前端添加BOM时,限制一次用户仅可操作一层BOM结构,不能多层联调整
这样一来,后端实现起来直接变得更加简单,什么互引用,反引用直接很简单一条SQL或Lambda表达式即可查询出来

本来两天的工作量,半天即可完成BOM模块的基本雏形了!

客户改需求了

刚敲完BOM模块,客户的新需求又来了(想打人,有没有......),这次需要加一个BOM版本号,也就是一个BOM需要保留多个版本结构!
想了一下,直接在BOM表里加一个字段即可,同一版本这个字段值相同,不同版本号不重复即可(这个需要考虑到,不然数据会出大问题),查询时候直接用Groug by进行分组,就能找到所有的辅料信息了!----> 说明了这样设计表结构,还是有很好的扩展性的。

文末总结

不管做什么,其实没有第一次的尝试,就没有后面更好的尝试!
第一次的经验也是很重要的
当初写这个功能的时候,我还是个刚入行的新手(现在也是菜鸡一枚),现在回忆起来,还是很有感慨的
要想成为高手,不犯错误是不可能的,犯错误,然后不停的思考,才能有进步。
屡战屡败,一站封神!这个一肯定是很多次!