/// <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; }
/// <summary> /// Executes a query and invokes a method with a DataReader of results. /// </summary> /// <param name="transaction">Should be null, transactions are not supported.</param> /// <param name="mapping">Class mapping for the table we're querying against. Optional, /// but not all columns may be properly typed if it is null.</param> /// <param name="query">The query to execute, should have come from CreateQuery.</param> /// <param name="invokeMe">The method to invoke with the IDataReader results.</param> /// <param name="parameters">A hashtable containing any values that need to be persisted through invoked method. /// The list of objects from the query will be placed here.</param> public override void ExecuteQuery(ITransaction transaction, ClassMapping mapping, IDaQuery query, DataReaderDelegate invokeMe, Hashtable parameters) { switch (_connDesc.Type) { case CsvConnectionType.Directory: case CsvConnectionType.FileName: case CsvConnectionType.Reader: // These are OK. break; default: throw new LoggingException("Connection does not support querying: " + _connDesc); } CsvDataReader reader = new CsvDataReader(this, mapping, ((UnqueryableQuery)query).Criteria); try { invokeMe.Invoke(parameters, reader); } finally { reader.Close(); } }
/// <summary> /// Gets a count of records for the given criteria. /// </summary> /// <param name="transaction">Should be null, transactions are not supported.</param> /// <param name="crit">The criteria to use for "where" comparisons.</param> /// <param name="mapping">The mapping of the table for which to build the query string.</param> /// <returns>The number of results found that matched the criteria.</returns> public override int GetCount(ITransaction transaction, ClassMapping mapping, DaoCriteria crit) { switch (_connDesc.Type) { case CsvConnectionType.Directory: case CsvConnectionType.FileName: case CsvConnectionType.Reader: // These are OK. break; default: throw new LoggingException("Connection does not support counting records: " + _connDesc); } CsvDataReader reader = new CsvDataReader(this, mapping, crit); int retVal = 0; try { while (reader.Read()) { retVal++; } } finally { reader.Close(); } return retVal; }
/// <summary> /// Deletes a data object record using the mapping and criteria for what's deleted. /// </summary> /// <param name="transaction">Should be null, transactions are not supported.</param> /// <param name="crit">Criteria for deletion. NOTE: Only the expressions are observed, /// other things (like "order" or start / limit) are ignored. /// WARNING: A null or empty (no expression) criteria will /// delete ALL records!</param> /// <param name="mapping">The mapping of the table from which to delete.</param> /// <returns>The number of records affected.</returns> public override int Delete(ITransaction transaction, ClassMapping mapping, DaoCriteria crit) { switch (_connDesc.Type) { case CsvConnectionType.Directory: case CsvConnectionType.FileName: // These are OK. break; default: throw new LoggingException("Connection does not support deleting: " + _connDesc); } // No way to selectively delete text from a text file, so instead we 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()); } CsvDataReader reader = new CsvDataReader(this, mapping, inverseCrit); try { TextWriter newWriter = new StreamWriter(newFile, false); try { newWriter.WriteLine(MakeHeaderRow(mapping)); 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 { newWriter.Close(); } } finally { reader.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 FastDAO<object>.UNKNOWN_NUM_ROWS; }