Using an AI Coding tool (WindSurf) to modify a Blazor app to replace enum lists with SQL tables. The process involved creating new tables, populating them from the enum values, and modifying the code to use the new tables. These properties were added as Foreign Key references in the dependant entity. Challenges included handling null values and ensuring proper loading of properties. This initially involved explicitly loading the FK data and then inserting the values into the list of of the dependent entity when the list is loaded. Later the solution involved adding name properties in the dependant entity that explicitly loaded the FK properties when referenced. This included inserting a default value (Unknown) when the FK value was null This Tabular approach allows for easier maintenance and updates without needing to rebuild or redeploy the app. Later, a more elegant solution was implemented by overriding the ToString method in the FK classes to return the Name property, which is called implicitly when the property is used in the UI code. This eliminated the need for additional properties in the dependent entity and provided a cleaner and more maintainable solution.

Preamble

“In the midst of all the joy wrt token costs with AI LLMs” I have been using AI for code development. In particular I have been using the WindSurf app with a Pro subscription. Last month with the changes made to Token consumption, I found that I needed to be a bit more prudent with the choice of LLM and the structure of queries. WindSurf now has daily and weekly quotas. If you choose to use a top level LLM then you blow you budget very quickly. I am though interested in discussions about the advantages and disadvantages of using LLMs with a larger quota cost in the coding context. Have there been any quantitative studies comparing efficiencies of low token cost LLMs with higher token cost LLMs? The problem though with such a study probably is that once a sequence of queries have been used to develop, say, an app, with one LLM, that information would probably filter through to a second sequence of the queries with an alternative LLM. Hard to make comparisons in a vacuum. Also, in making comparisons, would you focus upon how quickly the task was completed (read number of tokens*token cost), how much it could remember, how often it went around in circles or hallucinated, etc? Or how good the outcome was.

Nb: Just discovered this Leaderboard: Best LLM Leaderboard 2026 | AI Model Rankings

A Recent Task

I have in the last day or so decided to modify a Blazor Service app that has been in operation for several years with many library updates, code improvements and functional additions. The app is hosted online on Azure and provides a mechanism for Helpers to volunteer on behalf a sporting club for assigned tasks that the club has been by the sporting association for association meets. Each meet has a Location and Competition type.

    public enum Locations { Aberfeldie, Werribee, Williamstown, Doncaster, Knox, Lakeside, etc .., Other=255 }

    public enum CompetitionType { AVSL,VicChamps,AVSLPlayOffs,VicRelays,XCR21,Schools_XCR21,... etc, Other=255 }

The task here was to replace the enum lists for Location and Competition types with tables in the app’s SQL database. These entities don’t often require additional entries so to add additional locations or competitions, the approach has been to add them at the end of the list in the code, rebuild and then redeploy to Azure. It was decided to make the app a bit more “bullet proof” by doing this. The outcome at this stage is 2 new tables in the database with matching names to the enum names, along with a database Id. The code transposed the enums to populate the tables. Code was then modified to use the new entity’s Ids and names. After testing, the references to the enums were removed and the app was further tested. At this point, adding a new location or competition is done directly in the database management app (SSMS). A later refinement will be to facilitate this in the Blazor app by an Admin.

Experience in doing so

Query: Have 2 enum lists that what to migrate to sql tables It listed all enum types in the application Response: Specify which 2 enum lists you want to migrate to SQL tables Query: Data/Locations in Activitys.cs and Data/CompetitionType in AVSL.cs Do one at a time starting with Locations please. First Outcome (eventually): The Locations table was created in the database and populated from the enums via Entity Framework. Code was modified to load the table and use this in place of the Location enums. This all worked well when tested but later it was found that the Id for a location referred to a location incremented by one. This was manually fixed in the database management app. Luckily for later, the app repository was updated at this time.

Second enum Replacement

Query: Re: Data/CompetitionType enum in AVSL.cs Lets similarly make that a sql table as well This bumbled along going in circles and not having infinite memory was apt to repeat itself. Eventually I pulled the plug, cancelled and reverted to the last repository commit. This time I used WindSurf in a more managed way, not just saying, “Go for it!”. The proposed new approach was to:

  1. Generate the new table dbCompetition and add the enum Competition values as entries, in isolation.
  2. Leave the enum Competition property in Program class but add a new property dbCompetition property that uses values in dbCompetition table.
  3. Iterate through the Programs list and for each Competition property value, look up its corresponding value in dbCompetitions and insert the Id there into the Program instance dbCompetitionId property or insert the found dbCompetition directly in the Program instance dbCpmpetition property directly using Entity Framework. The actual steps taken for the second property mirrored what was had been added for the first property but were done manually.
var programs = await _context.AVSLPrograms.ToListAsync();

Steps 1 and 2 worked OK but step 3 required a bit “brute force”. It was found that when Programs list was loaded, and filtered, whilst the new property Ids where retrieved, the actual property for each instance was null. The new properties loading wasn’t working properly. A workaround was, whenever the Program list was retrieved, the list was iterated through and the property values were inserted by looking up their values in the new tables. This was rather cumbersome.
Later some lazy-loading code was added :

var programs = await _context.AVSLPrograms.Include(p => p.Location).Include(c => c.dbCompetition).ToListAsync();

When loaded as such, upon inspection, the Location and dbCompetition properties were still null. The solution was to add a name property for each to the Program class for each of the two properties that uses the values. This forces the property vale lookups. It also handles returning “Unknown” when the Id for a property is null. In the Program class:

[NotMapped]
[JsonIgnore]
public string dbCompetitionName
{
    get
    {
        return dbCompetition?.Name ?? "Unknown";
    }
}

Then use the dbCompetitionName in the UI code. Eg: Originally using the enum property:

<GridColumn Field="@(nameof(AVSLProgram.Competition))" Title="Competition" Width="150px" />

Was replaced with using the tabled property:

<GridColumn Field="@(nameof(AVSLProgram.dbCompetition))" Title="Competition" Width="150px" />

And then then the generated property:

<GridColumn Field="@(nameof(AVSLProgram.dbCompetitionName))" Title="Competition" Width="150px" />

Conclusion

This coding should be improved to implicitly get the Name property for both of these FK properties … later, but hey this is a significant improvement rom a coding perspective. When a new location or competition is needed, it can be directly added to their tables in the database without any need to rebuild or redeploy the app. (See below)

Later Refinements

The problem all along was when the second approach as above referring directly to the property, that properties rendered in the UI thus:

AthsEssAVHelpers.Data.dbCompetition
AthsEssAVHelpers.Data.Location

The previous version using enums, just literally turned the enum value into a string. The solution was to add a name property for each to the Program class for each of the two properties that uses the values. This forces the property value lookups. It also handles returning “Unknown” when the Id for a property is null. In the Program class. But that was overkill. What was needed was to add a ToString override method to the dbCompetition and Location classes. This is a much more elegant solution. The ToString method is called implicitly when the property is used in the UI code. So, for example, in the FK class:

public override string ToString()
{
    if (string.IsNullOrEmpty(Name))
        return "Unknown";
    return Name;
}

Note the override moniker which is needed to override the default ToString method. Then in the UI code, just use the dbCompetition or Location property directly. Eg:

<GridColumn Field="@(nameof(AVSLProgram.dbCompetition))" Title="Competition" Width="150px" />

When this is rendered, the ToString method for the dbCompetition class is called, which returns the Name property. This is a much cleaner solution than adding additional properties to the Program class. It also means that if we want to use the dbCompetition or Location properties elsewhere in the code, they will automatically return their Name when converted to a string, without needing to add additional properties or logic in the target entity. There is now no need for LocationName and dbCompetitionName properties in the Program class. This is a better and more maintainable solution. 🙂

Side comments

When setting an AI tool “loose” om your code, it is important to have a good repository management strategy. In this case, I had a good strategy of making regular commits to the repository as I made changes. This allowed me to easily revert to a previous commit if something went wrong. It also allowed me to track the changes that were made and understand the history of the code. When using an AI tool, it is also important to review the changes that are made and test them thoroughly before committing them to the repository. This can help catch any issues or bugs that may have been introduced by the AI tool. Overall, having a good repository management strategy is crucial when using AI tools for code development, as it provides a safety net and allows for better tracking and understanding of changes made to the codebase.

Another issue is when making changes to the database schema, it is important to have a good backup strategy in place, starting with a backup of the database elsewhere.. This can help prevent data loss if something goes wrong during the migration process. It is also important to test the changes in a staging environment before applying them to production, to ensure that everything works as expected and that there are no issues with the new schema or data. Additionally, when making changes to the database schema, and data migrations, it is important to consider the impact on existing code and queries that may be using the old schema, and to update them accordingly to avoid any issues or errors. Finally you need to understand how to undo a migration in concert with repository reversions.


 TopicSubtopic
<  Prev:   Azure Front Door Update
   
 This Category Links 
Category:Artificial Intelligence Index:Artificial Intelligence
<  Prev:   Checkers-Draughts Game