[00:02] development? I've been asked this question a bunch of times in the comments and I finally decided to make a video where I'm going to break down my approach to using AI tooling, mainly the cursor IDE for developing .NET [00:17] applications. So, if you watched any of my videos where I touch on AI generated coding, you know that I prefer using cursor. I pay the monthly subscription and I get pretty much all I need when it comes to AIdriven development. Now I [00:33] want to talk about my workflow when it comes to using cursor and I think this applies regardless of which AI tool you are using whether it's an ID or a CLI preference in my opinion. What matters is the workflow that you use when [00:49] interacting with AI. Now I'm going to make two presumptions when it comes to AIdriven development. The first one is that you know what you want to build and you also know how you will get there given enough time. The second one is [01:03] that you treat AI as your assistant and not necessarily as a replacement for you. We won't dive into whether AI is going to replace developers or not at some point in the future. That's a topic for a different video. So given these [01:17] presumptions, let's implement a semi-realistic use case where I take my application queries inside of this to-do app and I convert them from using EF core to fetch the data and map that to a DTO into using raw SQL with Dapper. So [01:34] whenever implementing something more complex than a single file, my workflow always starts with planning. Now cursor has this handy plan mode where you can ask it what you want to build and it's going to start out by generating a plan [01:48] for this. So let's give it a prompt that looks something like this. I want to migrate all my application queries ending with query handler from EF core to raw SQL with Dapper in order to improve performance. We'll create a new [02:01] connection. And I'm being specific here that I want to use the IDB connection interface that we'll use for Dapper queries. I don't want to touch the to send this off to cursor. Notice that I'm not using any specific AI. I just [02:17] set this to auto for most cases. And I let cursor choose whatever it thinks is the optimal result. So, what's going to happen now is cursor is going to scan my I have the required libraries implemented, and at the end of it all, [02:31] it might ask a couple of clarifying questions, and if it thinks it has everything it needs, it's going to go ahead and produce a plan. Now this is a cursor feature. However, this is just a markdown document. So you could generate [02:44] this with any AI tool out there. You could do this in Copilot for VS Code or Visual Studio. Ask it to first produce a plan instead of implementing any feature and output that plan as a markdown document. So what's neat about cursor is [02:58] I can now go ahead and review this document and see if I'm satisfied with everything inside. If I am, I can go ahead and click the build button and the required code. So this is the first [03:12] point that I'm trying to drive home. I don't treat AI as a vibe coding buddy. I'm being very specific with what I want it to do and I'm asking it to first produce a plan before we dive into any implementation specifics. Looking at the [03:26] plan itself and this is something else that I think it's important and that is reviewing the output of the AI. So in this case it's a plan. Later when it produces code we're going to review the code but first let's focus on the plan. [03:38] provider and this is going to be inside of an ISQL connection factory. There's a create connection method. All of that looks fine by me. So I'm going to go past that. Then it wants to add the Dapper package. Now I'm not sure if this [03:51] management. So I'm going to be specific about this. Make sure to use central package management. And in the bracket I'm going to say directory packages enough of a nudge for cursor to figure out what I'm trying to say here. Then it [04:07] wants to migrate my query handlers. Replace application DB context with SQL connection factory. Remove the using statement. Start using Dapper. Then it's going to rewrite my queries into the respective SQL format. Then we can touch [04:20] on the database internals here if we need to change anything. And in the end there's a list of files that are going to be modified. You can do a quick smoke test of this just to make sure that everything checks out. And let's say I'm [04:32] happy with all of this. I'm going to click build. And now cursor is going to start iterating on these to-dos. Now, if you think about it, this is how you would typically develop the project yourself. You would first plan out what [04:45] you want to do, break it down into some smaller steps, and then go ahead and I'm essentially recreating the workflow that I use in my day-to-day work. I'm just delegating it to the AI and I think this is an efficient approach. If anyone [05:00] has a better suggestion, please feel free to leave it in the comments. I'd like to know more about how you use AI tooling. Now, I'm going to wait up a and then we're going to take a look at the code that it produced for us. So, a [05:13] couple of moments later, we have our implementation in place and we can start reviewing what cursor has generated. So I'll begin with the directory packages drops and you can see that it specified the dapper and the mpgsql nougat [05:27] packages. Now I know from experience that the mpgsql package isn't necessary inside of my EF core provider which is this package here mpgqf core posgress. So we can go ahead and remove this. So I can go to this line of code and I can [05:43] say undo. Make sure to save this. And then in the application project I have to do the same for the MPGSQL reference. Dapper is all we need. So now let's take a look at the SQL connection factory. This checks out. Just a create [05:57] connection method. And in the implementation it's fetching my connection string and creating a new MPGSQL connection. So this is probably MPGSQL connection. So this is probably okay. One thing you may want to do is to [06:09] move this in a variable that you can return. And this just lets me open the connection before returning it from this method. Now, because I'm using MPGS SQL, I want to make sure that I'm returning an MPGSQL connection because cursor [06:22] harder to catch. But then again, this is something I know from experience. Now, the second thing here is that this isn't really the optimal way anymore at least to create an MPGSQL connection. So this is a shortcoming of AI tooling because [06:36] they are trained on existing code and not all of that code is up to date with the latest developments of a given library MPG SQL in this case. So this is again why it's important to review the generated code. So even though this is [06:50] correct or I may even have a typo here. We're going to catch that later. What I would actually want to do is move into using an MPGSQL data source which allows me to obtain a connection. Now, I could refactor this, but I'm going to leave it [07:03] like this for the time being. And let's take a look at the dependency injection function, I can actually make it a singleton because this is essentially a database connection. So, it doesn't really have to be scoped. And then if we [07:18] take a look at the queries, you can see that this correctly replaces my EF core implementation with a SQL query. I like that it's stored in a constant. And then it executes this using Dapper. There's also a using statement above where it [07:31] references Dapper. And I'm going to assume that this is correct. Assumption is the mutter of all messups, especially when it comes to AI generated code. But for the purpose of this demo, let's assume that this code is correct. Now, [07:45] what we would actually want to do is have either a strong set of test cases that I can run on demand and just make sure that this works as expected. Ideally, this would be an integration test using an actual database instance, [07:59] which is important because we are running raw SQL and with an actual database, I can execute this SQL against the database and just confirm that I'm are using something like an in-memory database, then you risk subtle bugs [08:12] creeping in. if you're only relying on tests for validating your code. So another thing I'm seeing here is the use of verbatim strings where the more popular approach would be using this syntax which lets me define a multi-line [08:25] string. However, once you do this once you can easily replicate it in your remaining queries as the AI is pretty quick to pick up what you're trying to do. So I can easily go ahead and fix this for all of the queries that I have [08:39] missing. So let's go ahead and add that. And then let's say I'm happy with all of this. I'm going to say keep all and accept all the suggestions from cursor. ourselves what's next. Now that I have the code that I was looking for, I [08:54] proceed to test it either by writing some test cases. Again, we could use AI here. It's enough that you have a couple of test cases as an example and it can write pretty detailed test cases from my experience that are going to cover the [09:07] behavior that you would end up testing yourself if you were writing the test cases. Another thing I highly recommend and honestly I hope that this is a given is that you're actually going to run this code and verify that it works. One [09:20] drawback of cursor is that it doesn't support the C devkit. So I don't have IntelliSense built-in. If I were using VS Code with Copilot then that part will be solved. But what I typically do is just switch to Visual Studio and verify [09:34] my code from there. So let's for example check the SQL connection factory just to make sure that we got the connection name correct and this wasn't the case. So this is something that you can easily catch if you just run a net build in the [09:47] terminal or you switch to Visual Studio and then build a project and then find and fix the problem. But either way be aware that AI will not produce perfect code on the first try. However, it might get you like 90% of the way there which [10:01] a significant time saving to be worth it to me. If you don't want to use cursor, that's fine. I mentioned that you have copilot in Visual Studio with a couple also bring your own model if you have an API key and implement everything I just [10:17] did directly from Visual Studio. If you'd like to see me explore this and share my opinions on Copilot Chat in Visual Studio, let me know in the comments and I'm going to cover that in a future video. In my opinion, AI [10:29] generated code is here to stay and I expect it to get better with time. One thing I don't have an answer for yet is what's going to happen with junior devs. Because if they rely too much on AI, they're going to fail to learn all the [10:43] expensive lessons that you would have learned otherwise if you were comes from exploring documentation, fixing difficult problems for days, debugging applications. It's not yet clear to me how you're going to attain [10:55] all those skills if you only rely on AI to produce code for you. Either way, if you enjoyed this video even a little bit, I ask of you to just smash that like button right below. Thanks a lot for watching and until next time, stay [11:08] for watching and until next time, stay awesome.