Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
1h 15m 23s
In Lesson 11 of Tim Corey's "C# App Start to Finish" series, Tim explains how to save data into text files using a text-based data connection. Tim begins by reminding viewers that, in the previous lesson, they set up the SQL connection and performed key housekeeping tasks. Now, the focus shifts to the Text Connection, and the goal is clear: make the text connection work just like the SQL connection, where the system can take a PrizeModel and return it with its ID properly filled out. Tim emphasizes that the video will show a complete workflow for storing, reading, and updating data using plain text files.
Tim starts by opening the Text Connector inside the DataAccess folder. He deletes the sample code and begins from scratch. He explains that unlike SQL, text files don't provide smart database features like auto-incrementing IDs. So the first task is deciding where to store the text files.
Tim proposes a clean design: store each model in its own text file. For example, PrizeModel will have its own file called PrizeModels.csv, while other models like MatchupModel will each have separate files. Tim compares this structure to SQL tables - each file becomes a "table" containing a list of that model. This makes data easy to manage and prevents mixing different model types together.
Tim explains that instead of storing a single file name, you store a path to the folder where all files will be saved. This path is placed in the app.config under appSettings. Tim adds a new key-value pair:
He emphasizes using the correct Windows syntax and avoids ending the path with a slash, since he prefers adding the slash only when building the full file path. This setup is crucial because it makes the application flexible - if the storage location changes, you only update the app.config.
Tim outlines a clear plan for saving a prize:
Tim explains that text files are "stupid" compared to SQL databases. SQL can manage IDs automatically, but text files require the developer to implement logic manually. This is why Tim breaks the process into smaller methods to keep the code clean and reusable.
Tim creates a new class called TextConnectorProcessor. He places it inside the DataAccess folder but in a different namespace to avoid cluttering the main namespace. Tim explains that namespaces are flexible and can be customized, but he recommends keeping them simple and clean.
He makes the class public static and starts building helper methods.
Tim creates an extension method:
public static string FullFilePath(this string fileName)
This method combines the filePath from app.config with the file name to generate the full file path. Tim demonstrates how to use ConfigurationManager.AppSettings["filePath"] and explains the necessity of escaping slashes in C# strings (using \\).
He then converts the method into an extension method so it can be used like this:
"PrizeModels.csv".FullFilePath()
Tim explains that this extension method is only needed in the text connector, so he keeps it in a separate namespace to avoid showing it everywhere in the solution.
Next, Tim creates another extension method:
public static List<string> LoadFile(this string file)
This method checks if the file exists using File.Exists(). If the file doesn't exist, it returns an empty list. If it does exist, it reads all lines using File.ReadAllLines() and converts them into a list.
Tim highlights the importance of handling missing files properly since this is common in the first run of the application.
Tim creates a method to convert the loaded text lines into a list of PrizeModel:
public static List<PrizeModel> ConvertToPrizeModels(this List<string> lines)
He explains the use of comma-separated values (CSV) where each line contains fields separated by commas. Tim splits each line into columns and parses them into the appropriate data types:
Tim also explains that he intentionally allows the application to crash if the data is invalid. This helps reveal problems early instead of continuing with corrupted data.
Tim returns to the TextConnector and explains how to find the highest ID:
int currentID = prizes.OrderByDescending(x => x.ID).First().ID + 1;
He notes this will crash if the file is empty, so he adds a check:
if(prizes.Count > 0)
{
currentID = prizes.OrderByDescending(x => x.ID).First().ID + 1;
}
This ensures the first record gets an ID of 1.
Tim adds the new prize to the list and then converts the list back into text lines:
public static void SaveToPrizeFile(this List<PrizeModel> models, string fileName)
He uses string interpolation to create each CSV line and adds it to a list of strings. Finally, he uses:
File.WriteAllLines(fileName.FullFilePath(), lines);
Tim explains that WriteAllLines overwrites the file, which is desired behavior because it refreshes the data with updated content.
Tim concludes the method by returning the PrizeModel with the assigned ID. This makes the new prize usable in the rest of the application, just like SQL.
Tim switches to Program.cs and changes the data connection from SQL to Text. When he runs the application and creates prizes, the system initially crashes due to missing records. Tim quickly fixes the bug with the if(prizes.Count > 0) check, then runs again.
He demonstrates that the data is correctly saved into the PrizeModels.csv file and shows how the file can be opened in Notepad or Excel.
Tim ends the lesson by reminding viewers that the extension methods only appear when the correct namespace is included. This avoids clutter and potential naming conflicts. He notes that these two lessons create a strong foundation for the rest of the application and sets the stage for future development.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy