• 为数据库定长字段添加数据


    为数据库定长字段添加数据

    需求:使用C#做一个工具,把csv中的数据追加到DB中。
    描述:表PharmacyMemo中存在一个定长600的字段memo,现在有一个csv文件记录了患者的memo数据,根据患者ID+日期,如果数据库中存在该患者数据,那么就把csv的memo内容添加到既存数据中,如果不存在那么就插入一条新的数据。
    已知csv文件中的memo最长不会超过600。

    因为觉得还可以优化,先记录下简单实现,后面有时间再看看怎么优化。

    // 把文件转为DTO
    List<MemoCsvDto> csvDtoList = ConvertCsvFileToDto(memoFile);
    // 根据患者号分组
    Dictionary<int, List<MemoCsvDto>> benkjnoDic = csvDtoList.GroupBy(s => s.NextKjno)
                    .ToDictionary(g => g.Key, g => g.ToList());
    // 然后根据患者号排序
    var sortedCsvDic = (from entry in benkjnoDic
                            orderby entry.Key
                        select entry);
    
    // 获得数据库中所有PharmacyMemo数据(因为库中数据不是太多,因此直接查全表,这里可以根据情况改进)
    // C# 版本较低时不支持 out int intValue的形式,必须提前声明
    int maxKey = 0;
    List<PharmacyMemoDto> existPharmacyMemoList = GetAllKanjaPharmacyMemos(out maxKey);
    // 根据患者号加日期分组
    Dictionary<string, List<PharmacyMemoDto>> existPharmacyMemoDic =
            existPharmacyMemoList.GroupBy(s => GetPharmacyMemoGroupKey(s))
            .ToDictionary(g => g.Key, g => g.ToList());
    
    // 准备好要插入的数据
    List<PharmacyMemoDto> insertList = new List<PharmacyMemoDto>();
    List<PharmacyMemoDto> updateList = new List<PharmacyMemoDto>();
    // 字符串拼接的stringBuilder
    StringBuilder sb = new StringBuilder();
    
    foreach (var kjnoPair in sortedCsvDic)
    {
        int nextKjno = kjnoPair.Key;
        // 判断非法数据,如果患者表中没有这个患者号就不继续
        if (!existNextKjnoSet.Contains(nextKjno))
        {
            // C#版本较低时不支持$""的形式
            Log.Info(string.Format("NEXTの患者テーブルにKJNO:{0}はありません。", nextKjno));
            continue;
        }
    
        List<MemoCsvDto> oneKanjaCsvList = kjnoPair.Value;
        // 根据日期分组
        // 因为C#的dictionary的键不能为null,因此使用一个自定义类来作为Key
        Dictionary<NullableKey<DateTime?>, List<MemoCsvDto>> groupByEditDayDic = 
                oneKanjaCsvList.GroupBy(s => new NullableKey<DateTime?>(s.EditDay))
                        .ToDictionary(g => g.Key, g => g.ToList());
    
        foreach (var editDayPair in groupByEditDayDic)
        {
            sb.Clear();
            DateTime? editday = editDayPair.Key.Value;
            List<MemoCsvDto> tobeSaveList = editDayPair.Value.OrderBy(s => s.RowNumber).ToList();
    
            string csvGroupKey = GetPharmacyMemoGroupKey(nextKjno, editday);
    
            PharmacyMemoDto dbDto;
            if (existPharmacyMemoDic.ContainsKey(csvGroupKey))
            {
                // 找到DB主键最大的数据
                dbDto = existPharmacyMemoDic[csvGroupKey].OrderBy(dto => dto.MemoCode).Reverse().First();
                sb.Append(dbDto.MemoText);
            }
            else
            {
                // 库中不存在时就虚构一个数据
                maxKey++;
                dbDto = new PharmacyMemoDto();
                dbDto.MemoCode = maxKey;
                dbDto.OperatorCode = nextKjno;
                dbDto.OperatorFlag = 1;
                dbDto.MemoText = string.Empty;
                dbDto.EditDay = editday ?? DEFAULT_EDITDAY;
                // 自定义追加的字段,非DB字段
                dbDto.IsDbData = false;
    
            }
    
            PharmacyMemoDto currentDto = dbDto;
            // 向insertList或者updateList插入的时机就是长度大于600或者最后一个
            {
                for (int i = 0; i < tobeSaveList.Count; i++)
                {
                    MemoCsvDto csvDto = tobeSaveList[i];
    
                    // 长度大于600时
                    if ((Encoding.Default.GetByteCount(sb.ToString())
                            + Encoding.Default.GetByteCount(csvDto.Memo)
                            + Encoding.Default.GetByteCount(Environment.NewLine)) > 600)
                    {
                        // 保存当前dto
                        currentDto.MemoText = sb.ToString();
                        if (currentDto.IsDbData)
                        {
                            updateList.Add(currentDto);
                        }
                        else
                        {
                            insertList.Add(currentDto);
                        }
    
                        sb.Clear();
                        sb.Append(csvDto.Memo);
    
                        // 创建新的dto
                        maxKey++;
                        currentDto = new PharmacyMemoDto();
                        currentDto.MemoCode = maxKey;
                        currentDto.OperatorCode = nextKjno;
                        currentDto.OperatorFlag = 1;
                        currentDto.MemoText = sb.ToString();
                        currentDto.EditDay = editday ?? DEFAULT_EDITDAY;
                        currentDto.IsDbData = false;
                    }
                    else
                    {
                        // 小于600时只需要拼接memo字段即可
                        if (sb.ToString() == "")
                        {
                            sb.Append(csvDto.Memo);
                        }
                        else
                        {
                            sb.AppendLine().Append(csvDto.Memo);
                        }
                    }
    
                    if (i == tobeSaveList.Count - 1)
                    {
                        currentDto.MemoText = sb.ToString();
                        if (currentDto.IsDbData)
                        {
                            updateList.Add(currentDto);
                        }
                        else
                        {
                            insertList.Add(currentDto);
                        }
                    }
                }
            }
        }
    }
    
    
    /// <summary>
    /// use this class to solve dictionary's key can't be null
    /// </summary>
    /// <typeparam name="T"></typeparam>
    class NullableKey<T>
    {
        private readonly T _value;
    
        public NullableKey(T value)
        {
            _value = value;
        }
    
        public T Value
        {
            get { return _value; }
        }
    
        public override bool Equals(object obj)
        {
            var key = obj as NullableKey<T>;
            return key != null &&
                    EqualityComparer<T>.Default.Equals(Value, key.Value);
        }
    
        public override int GetHashCode()
        {
            return -1937169414 + EqualityComparer<T>.Default.GetHashCode(Value);
        }
    }
    

    题外话:
    如果再复杂一点,可以根据DFA画出状态变化图,然后在进行编码。

  • 相关阅读:
    0diff算法参考资料
    js 对象属性值
    一些带有设计模式的优秀代码
    vue 配置多页面
    cms 管理系统
    网络技术:EtherChannel 链路汇聚
    网络技术:VLAN 中继协议(VTP)
    网络管理:管理信息库
    网络管理:抽象语法表示 ASN.1
    网络管理:基本编码规则(BER)
  • 原文地址:https://www.cnblogs.com/lixin-link/p/14675678.html
Copyright © 2020-2023  润新知