C# Oracle 之Insert 与 Update 的封装
时间:2011-04-14 来源:oyster.oy
最近在写一个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秒,谢谢大家。
相关阅读 更多 +










