/// <summary>
/// Updates a data object record using the "table" and a list of column/value pairs.
/// </summary>
/// <param name="transaction">Should be null, transactions are not supported.</param>
/// <param name="mapping">The mapping of the table or other data container we're dealing with.</param>
/// <param name="crit">All records matching this criteria will be updated per the dictionary of
/// values.</param>
/// <param name="propValues">A dictionary of column/value pairs for all non-ID columns to be updated.</param>
/// <returns>The number of records affected.</returns>
public override int Update(ITransaction transaction, ClassMapping mapping, DaoCriteria crit, IDictionary<string, object> propValues)
{
switch (_connDesc.Type)
{
case CsvConnectionType.Directory:
case CsvConnectionType.FileName:
// These are OK.
break;
default:
throw new LoggingException("Connection does not support updating: " + _connDesc);
}
// No way to selectively update text from a text file, so instead we first copy all
// the rows that don't match the criteria into a new file.
string existingFile = GetFileName(mapping);
string newFile = existingFile + ".new";
DaoCriteria inverseCrit = new DaoCriteria();
foreach (IExpression expr in crit.Expressions)
{
inverseCrit.Expressions.Add(expr.Invert());
}
TextWriter newWriter = new StreamWriter(newFile, false);
int rowsUpdated = 0;
try
{
newWriter.WriteLine(MakeHeaderRow(mapping));
// Copy the rows that don't match...
CsvDataReader reader = new CsvDataReader(this, mapping, inverseCrit);
try
{
int numCols = reader.FieldCount;
while (reader.Read())
{
for (int x = 0; x < numCols; x++)
{
if (x > 0)
{
newWriter.Write(",");
}
newWriter.Write(QuoteValue(reader.GetValue(x)));
}
newWriter.WriteLine();
}
}
finally
{
reader.Close();
}
// Copy (modified) the rows that do match...
reader = new CsvDataReader(this, mapping, crit);
try
{
IDictionary<int, object> replacements = new CheckedDictionary<int, object>();
foreach (KeyValuePair<string, object> kvp in propValues)
{
replacements[reader.GetColumnIndex(kvp.Key)] = kvp.Value;
}
int numCols = reader.FieldCount;
while (reader.Read())
{
rowsUpdated++;
for (int x = 0; x < numCols; x++)
{
if (x > 0)
{
newWriter.Write(",");
}
// Use the updated value if one was provided.
object val = replacements.ContainsKey(x)
? replacements[x] : reader.GetValue(x);
newWriter.Write(QuoteValue(val));
}
newWriter.WriteLine();
}
}
finally
{
reader.Close();
}
}
finally
{
newWriter.Close();
}
// Now move the old file out of the way and replace it with the new one.
File.Replace(newFile, existingFile, existingFile + ".old", true);
return rowsUpdated;
}