Before reading: If you're looking for a good experience with AI, this article is not for you.
Very disappointing—it doesn't save time or effort. I still need to refactor the code for readability and maintainability.
Scenario - Translating from MongoDB to PostgreSQL
In our open-source feature flag project, FeatBit, we originally used MongoDB as our primary database. Based on customer feedback, we are now adding support for PostgreSQL. We used the MongoDB C# Driver SDK for queries with MongoDB, but we are transitioning to Entity Framework to support multiple databases within the same codebase.
This article demonstrates how we translated MongoDB C# Driver code to support PostgreSQL with Entity Framework using VSCode Copilot Edits and the Claude Sonnet 3.7 model, using a specific service called InsightService
.
Service Interface and Implementation
We have an interface called IInsightService
, which includes two methods: TryParse
and AddManyAsync
. The TryParse
method is used to parse a JSON string into an object, while the AddManyAsync
method adds multiple insight events to the database.
public interface IInsightService
{
bool TryParse(string json, out object insight);
Task AddManyAsync(object[] insights);
}
We had an implementation of InsightService
for MongoDB using the MongoDB C# Driver. Here's the original code:
public class InsightService(MongoDbClient mongoDb) : IInsightService
{
public bool TryParse(string json, out object? insight)
{
try
{
insight = Parse();
}
catch
{
insight = null;
}
return insight != null;
object Parse()
{
var jsonNode = JsonNode.Parse(json)!.AsObject();
// Replace uuid with _id
jsonNode["_id"] = jsonNode["uuid"]!.GetValue<string>();
jsonNode.Remove("uuid");
// Convert properties JSON string to object
jsonNode["properties"] = JsonNode.Parse(jsonNode["properties"]!.GetValue<string>());
// Convert timestamp to UTC DateTime
var timestampInMilliseconds = jsonNode["timestamp"]!.GetValue<long>() / 1000;
var timestamp = DateTimeOffset.FromUnixTimeMilliseconds(timestampInMilliseconds).UtcDateTime;
jsonNode["timestamp"] = timestamp;
// Convert JSON object to BSON document
var bsonDocument = BsonDocument.Parse(jsonNode.ToJsonString());
// Change timestamp type to DateTime, otherwise it will be String
bsonDocument["timestamp"] = timestamp;
return bsonDocument;
}
}
public async Task AddManyAsync(object[] insights) =>
await mongoDb.CollectionOf("Events").InsertManyAsync(insights as BsonDocument[]);
}
Now, we need to translate the logic in the TryParse
method and the database interaction code in AddManyAsync
to support PostgreSQL with Entity Framework.
Translating Logical Code to Support PostgreSQL
The TryParse
method in the MongoDB version of the service returned a BsonDocument, which is a MongoDB-specific type. To support PostgreSQL, we need to change it to a generic object type. Here's the prompt I used to translate the code:
I have a InsightService.cs in /Services/mongodb folder,
another InsightService.cs in /Services/EntityFrameworkCore folder
I need to translate from `TryParse` method in InsightService.cs in /Services/mongodb folder to `TryParse` method in InsightService.cs in /Services/EntityFrameworkCore folder
In the TryParse method in InsightService.cs in /Services/mongodb folder, it useed MongoDB C# Driver to convert a json string to BsonDocument type object.
But in the InsightService.cs in /Services/EntityFrameworkCore folder, the return value should be "object" a dynamic or expandoobject,
The image below shows the translated code in the IDE:
It correctly updated the TryParse
method in the appropriate file. However, the generated code was incorrect. So, I had to modify my prompt to get it to work:
in TryParse method, deserialize json variable from string to object. THe json string format is like below:
{
"uuid": // STRING, Primary Key
"distinct id": // STRING
"env_id": // STRING
"event": // STRING
"properties": // JSON string
"timestamp": // TIMESTAMP long
}
As shown in the image above, it worked, but the result was neither clean nor optimal. For example, on line 13, an unnecessary option
variable was declared and assigned but never used. I had to refactor the code to improve its readability and maintainability.
Translating Database Interaction Code to Support PostgreSQL
The AddManyAsync
method in the MongoDB version of the service used the InsertManyAsync
method from the MongoDB C# Driver to insert multiple documents into the database. We needed to modify it to use Entity Framework to support PostgreSQL.
I am not posting any prompts or images for this section because, despite multiple attempts, I was unable to get correct code from AI. Ultimately, I wrote the implementation myself.
Final code
Here’s my final refactored code. From my perspective, this version is much cleaner and more readable than the AI-generated code. Most importantly, it works correctly and took less time than iterating with AI.
public bool TryParse(string json, out object? insight)
{
try
{
insight = Parse();
}
catch
{
insight = null;
}
return insight != null;
object Parse()
{
using var jsonDocument = JsonDocument.Parse(json);
var root = jsonDocument.RootElement;
var timestampMs = root.GetProperty("timestamp").GetInt64() / 1000;
var timestamp = DateTimeOffset.FromUnixTimeMilliseconds(timestampMs).UtcDateTime;
var item = new
{
uuid = root.GetProperty("uuid").GetGuid(),
distinct_id = root.GetProperty("distinct_id").GetString(),
env_id = root.GetProperty("env_id").GetString(),
@event = root.GetProperty("event").GetString(),
properties = root.GetProperty("properties").ToString(),
timestamp
};
return item;
}
}
public async Task AddManyAsync(object[] insights)
{
var connection = dbContext.Database.GetDbConnection();
const string sql = """
insert into events (id, distinct_id, env_id, event, properties, timestamp)
values (@uuid, @distinct_id, @env_id, @event, @properties::jsonb, @timestamp)
""";
await connection.ExecuteAsync(sql, insights);
}
Conclusion
AI did not save me time or effort in this case.
- It couldn't generate clean and correct code directly—I still had to refactor it for readability and maintainability.
- Most of the time, it provided incorrect answers. I tried to refine my prompt to be as precise as possible, but it still didn’t work.
We'll see if future AI models perform better.