根据设计当MakeOld后(在读取数据库后,或者手动调用),对记录(SubSonic生成的类)属性附值时,Sonic会检测这个Value是否与原来的不同,只有值不同时才会附值成功,并将该列添加到DirtyColumns,而DirtyColumns中的列才会被Update采用,一般情况下 只要所有列中有一个列的是Dirty==true(被更改过),那么在Save时就会采用Update,
注意:SubSonic中判断是否采用Update判断“全部字段集合”中是否存在一个字段被更改,而生成Update命令时使用的集合是DirtyColumns集合,而不是直接从全部字段集合中查找那些被更改的字段,在多数情况下不会出问题,但有些时候可能带来意想不到的问题,参考下面的场境3。
//=============参考代码1================
public bool IsDirty
{
get
{
foreach(TableColumnSetting setting in this)
{
if(setting.IsDirty)
return true;
}
return false;
}
//set
//{
// foreach (TableColumnSetting setting in this)
// setting.IsDirty = value;
//}
}
//============参考代码2============
public QueryCommand GetSaveCommand(string userName)
{
if(IsNew)
return GetInsertCommand(userName);
if(IsDirty)
return GetUpdateCommand(userName);
return null;
}
如果您对记录未做任何更改而直接调用 .Save()时会根据IsNew与IsDirty的取值来决定采用Insert或Update。
如果两个多是false,那么就返回null.那么Save操作将什么都不做。
//============参考代码3============
QueryCommand cmd = GetSaveCommand(userName);
if(cmd == null)
return;
场境1:
Employe emp=new Employe(1);//加载一个员工数据
//这个时候 IsNew=false,IsDirty=false
emp.Name=emp.Name; //没有改变
emp.Save();//这里的Save方法将不做任何处理
场境2:
Employe emp=new Employe(1);
emp.Name=txtName.txt;//假设您在文本框中调整了Name取值
//这个时候 isNew=false;IsDirty=true;
emp.Save();将使用Update,并且只更新Name字段。
场境3:(报错)
Employe emp=new Employe(1);
Employe backEmp=new Employe();
backEmp.CopyFrom(backEmp);
//copyFrom后会backEmp.IsDirty全部是true
//参考代码7
backEmp.Name="xxxx";
backEmp.MackOld();//将IsNew设置成False
backEmp.Save(); //报错,IsDirty=True,而DirtyColumns为空,
//生成 Update Employe Set Where EmpoyeId=1 这样的错误TSQL
场境4:(报错)
Employe emp=new Employe(1);
Employe backEmp=new Employe();
backEmp.CopyFrom(backEmp);
backEmp.MackOld();
backEmp.Name=backEmp.Name;
backEmp.Save();//这时IsDirty是True,而DirtyColumns为空
正确作法,应该在backEmp.MackOld();后再调用backEmp.MackClear();
//=============参考代码8=================
/// <summary>
/// Called after any property is set. Sets IsDirty to <c>true</c>.
/// </summary>
public void MarkClean()
{
foreach(TableSchema.TableColumnSetting setting in columnSettings)
setting.IsDirty = false;
DirtyColumns.Clear();
}
//========参考代码4==========
/// <summary>
/// Called after Update() invokation. Sets IsNew to <c>false</c>.
/// </summary>
public void MarkOld()
{
IsLoaded = true;
_isNew = false;
}
//========参考代码5======================
/// <summary>
/// Copies the passed-in instance settings to this instance
/// </summary>
/// <param name="copyInstance">The copy instance.</param>
public void CopyFrom(T copyInstance)
{
if(copyInstance == null)
throw new ArgumentNullException("copyInstance");
foreach(TableSchema.TableColumnSetting setting in copyInstance.columnSettings)
SetColumnValue(setting.ColumnName, setting.CurrentValue);
}
//========参考代码6======================
/// <summary>
/// Sets a value for a particular column in the record
/// </summary>
/// <param name="columnName">Name of the column, as defined in the database</param>
/// <param name="oValue">The value to set the type to</param>
public void SetColumnValue(string columnName, object oValue)
{
columnSettings = columnSettings ?? new TableSchema.TableColumnSettingCollection();
// add the column to the DirtyColumns
// if this instance has already been loaded
// and this is a change to existing values
if(IsLoaded && !IsNew)
{
TableSchema.Table schema = GetSchema();
object oldValue = null;
string oldValueMsg = "NULL";
string newValueMsg = "NULL";
bool areEqualOrBothNull = false;
try
{
oldValue = columnSettings.GetValue(columnName);
}
catch {}
if(oldValue == null && oValue == null)
areEqualOrBothNull = true;
else
{
if(oldValue != null)
{
oldValueMsg = oldValue.ToString();
areEqualOrBothNull = oldValue.Equals(oValue);
}
if(oValue != null)
newValueMsg = oValue.ToString();
}
TableSchema.TableColumn dirtyCol = schema.GetColumn(columnName);
if(dirtyCol != null && !areEqualOrBothNull)
{
string auditMessage = String.Format("Value changed from {0} to {1}{2}", oldValueMsg, newValueMsg, Environment.NewLine);
TableSchema.TableColumn dirtyEntry = DirtyColumns.GetColumn(columnName);
if(dirtyEntry != null)
{
DirtyColumns.Remove(dirtyEntry);
auditMessage = String.Concat(dirtyCol.AuditMessage, auditMessage);
}
dirtyCol.AuditMessage = auditMessage;
DirtyColumns.Add(dirtyCol);
}
}
columnSettings.SetValue(columnName, oValue);//这里最终调用参考代码7
}
//============参考代码7============
/// <summary>
/// Gets or sets the current value.
/// </summary>
/// <value>The current value.</value>
public object CurrentValue
{
get { return _currentValue; }
set
{
if(value == null && _currentValue == null)
return;
if(value != null)
{
if(value.Equals(_currentValue))
return;
}
_currentValue = value;
_isDirty = true;
}
}