• C# Oracle 之Insert 与 Update 的封装


    最近在写一个Asp.net 的框架,在本地搭建了数据缓存,采用了 定时的lazy fresh的过期方式,

    但是大量的数据其实是没有改变的,改变的只是很小的部分,这个时候缓存过期,全部重新刷新数据就显得非常浪费了。

    思来想去,觉得我可以从数据库的更新方法下手,于是有了下面这些尝试了。

    在Oracle 中Insert 语句是可以使用 returning 返回新增的记录的。

    于是我们的Insert 语句就是这样了.

    INSERT INTO TableName (UniqueColumn,OtherColumns)
    VALUES(Table_SEQ.Nextval,Values) RETURNING UniqueColumn INTO :Unique_Id。

    这样执行之后,我就可以通过Out参数 Unique_Id 获取新增的记录的主键啦。

    附C#:

    public override object Insert(EditorParams pm)
            {
                if (pm != null && pm.EditValues.Count > 0)
                {
                    QuerySetting qs = ConfigEnginer.Instance.DataModels[pm.ModelType];
                    string insertformart = @"INSERT INTO #OysterVal:TableName# (#OysterVal:UniqueColumn#,#OysterVal:Columns#)
    VALUES(#OysterVal:TableName#_SEQ.Nextval,#OysterVal:Values#) RETURNING #OysterVal:UniqueColumn# INTO :Unique_Id";
    
                    Dictionary<string, string> vals = new Dictionary<string, string>();
                    List<IDataParameter> parms = new List<IDataParameter>();
    
                    vals.Add("TableName", qs.TableName);
                    vals.Add("UniqueColumn", qs.UniqueColumn.ColumnName);
                    vals.Add("Columns", pm.InsertColumns);
                    vals.Add("Values", pm.InsertValues);
    
                    //System.Nullable
                    var Unqtype = qs.UniqueColumn.PropertyType;
                    if (Unqtype.FullName.Contains("System.Nullable"))
                    {
                        var types = Unqtype.GetGenericArguments();
                        if (types != null && types.Length > 0)
                        {
                            Unqtype = types[0];
                        }
                    }
    
                    var pr = new OracleParameter(":Unique_Id", Activator.CreateInstance(Unqtype));
                    pr.Direction = ParameterDirection.InputOutput;
                    parms.Add(pr);
                    parms.AddRange(pm.DataParms);
    
                    string sql = insertformart.ToOysterTemplate(vals);
                    pm.EffectCount = DbEnginer.Instance.ExecuteNonQuery(sql, parms.ToArray());
                    pm.EffectUniqueIds.Add(pr.Value);
                    return pm.EffectUniqueIds[0];
                }
                else
                {
                    throw new Exception("请检查传入的EditParams,更新列数据不能为空!");
                }
    
                return null;
            }
    

    仅供参考,里面使用到的其他类型引用,以后会慢慢分享。

    而UPDATE 则可以这样:SELECT UniqueColumn FROM TableName WHERE Condition FOR UPDATE。

    将要更新的行Select 出来,并且加上Update 的锁。保证Update按顺序执行,而不会错乱。

    附C#代码:

    public override int Update(EditorParams pm)
            {
                if (pm != null && pm.EditValues.Count > 0)
                {
                    try
                    {
                        QuerySetting qs = ConfigEnginer.Instance.DataModels[pm.ModelType];
                        string selectforupdatestr = "SELECT #OysterVal:UniqueColumn# FROM #OysterVal:TableName# WHERE #OysterVal:Condition# FOR UPDATE";
                        List<IDataParameter> parms = new List<IDataParameter>();
                        string cond = pm.condition.ToString(parms);
    
                        Dictionary<string, string> dic = new Dictionary<string, string>();
                        dic.Add("UniqueColumn", qs.UniqueColumn.ColumnName);
                        dic.Add("TableName", qs.TableName);
                        dic.Add("Condition", cond);
    
                        string selectsql = selectforupdatestr.ToOysterTemplate(dic);
                        DbEnginer.Instance.DbConnection.IsReaderReading = true;
                        var ds = DbEnginer.Instance.ExecuteQuery(selectsql, parms);
                        if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
                        {
                            dic.Add("Columns", pm.UpdateColumns);
                            List<object> ids = new List<object>();
                            for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                            {
                                if (!ds.Tables[0].Rows[i][0].Equals(DBNull.Value))
                                {
                                    ids.Add(ds.Tables[0].Rows[i][0]);
                                }
                                if ((i > 0 && i % 999 == 0) || i == ds.Tables[0].Rows.Count - 1)
                                {
                                    var condition = Condition.New(qs.ClassType, qs.UniqueColumn.Property, ConditionOperator.In, ids);
                                    parms = new List<IDataParameter>();
                                    cond = condition.ToString(parms);
                                    dic["Condition"] = cond;
                                    string updatestr = "UPDATE #OysterVal:TableName# SET #OysterVal:Columns# WHERE #OysterVal:Condition#";
                                    string updatesql = updatestr.ToOysterTemplate(dic);
                                    foreach (var p in pm.DataParms)
                                    {
                                        var temp = DbEnginer.Instance.NewDataParameter(p.ParameterName);
                                        temp.ParameterName = p.ParameterName;
                                        temp.DbType = p.DbType;
                                        temp.Direction = p.Direction;
                                        temp.Value = p.Value;
                                        parms.Add(temp);
                                    }
                                    pm.EffectCount += DbEnginer.Instance.ExecuteNonQuery(updatesql, parms);
                                    pm.EffectUniqueIds.AddRange(ids);
                                    ids.Clear();
                                }
                            }
                            DbEnginer.Instance.ExecuteNonQuery("commit");
                        }
                    }
                    catch (Exception ex)
                    {
                        DbEnginer.Instance.ExecuteNonQuery("rollback");
                        throw ex;
                    }
                    finally
                    {
                        DbEnginer.Instance.DbConnection.IsReaderReading = false;
                        DbEnginer.Instance.DbConnection.Close();
                    }
                }
                else
                {
                    throw new Exception("请检查传入的EditParams,更新列不能为空!");
                }
                return pm.EffectCount;
            }
    

    哈哈,先就这样吧,只是分享一个思路,不过这样的效率不是很好。10000条Insert 12秒,Update 4秒,谢谢大家。

    -------------------------------------------------- oyster:授人者方为师!
  • 相关阅读:
    杭电2031进制转换
    杭电2033人见人爱A+B
    【转】到底怎么样才叫看书?
    方便单个实体更新的DbContext扩展方法,比如Edit页面
    使用Newtonsoft.Json
    代码配置 vs. 配置文件
    进程到创建
    C#+VBA 操作EXCEL(转)
    基于定位的社交应用Foursquare开源网址(wp7)
    深入理解计算机系统实验
  • 原文地址:https://www.cnblogs.com/touch/p/2016431.html
Copyright © 2020-2023  润新知