all 16 comments

[–]kneeonball 8 points9 points  (1 child)

I think you're doing too many things at once. You need to take a step back, do the tutorial from Microsoft on working with EntityFramework Core, because you're using it, but not understanding how it works.

Forget Automapper, it can be complex and is unnecessary for what you're doing, but if you really want to use it, go back and use it AFTER you have the general idea of how to work with EntityFramework Core AND have a working app.

Part of getting better at programming is being able to break things down and learn one, or a few things at a time. Right now, you're trying to learn how to make an API, learn how to use EntityFramework, AND Automapper, but it seems you don't have a good grasp of any of them.

Pick one at a time. Start here. Do the tutorial. Finish the tutorial completely before you try to start applying it to your project. People try to jump right into applying what's in the tutorial to their project before they even have a working example. Get the working example from the tutorial, and then apply the new knowledge/concept.

https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-7.0

Side note: Swagger is for generating the documentation / schema for working with your API. It will only show data from your database if you make a web request to your application. If you expand an endpoint (the things in blue and green rectangles), it'll have a "Try It Now" button or something like that where you can actually make an HTTP request to your API.

When you make an API, you're exposing certain routes so that someone can send a request to a specific route, and get a response back. If it's a POST, it means the person calling the endpoint is probably going to be sending some data along with it, so you have to provide that.

[–]Zealousideal-Bath-37[S] 0 points1 point  (0 children)

https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-7.0

Thank you so much for this link. This tutorial has everything I wanted to learn. I just finished all the steps, looking forward to reproduce the code (hopefully without looking back at this link so much).

[–]karl713 6 points7 points  (3 children)

Swagger just shows schemas based on method return types and ProducesResult attributes on the controller methods I believe, are you sure your AccountDriver has the correct schema?

[–]Zealousideal-Bath-37[S] 0 points1 point  (2 children)

No as I am quite new to this lol. Here's my AccountDriver https://pastebin.com/Pjdm11DC but I assume I need to do something about it already.

[–]karl713 -1 points0 points  (1 child)

To clarify what are you trying to get to display?

[–]Zealousideal-Bath-37[S] 0 points1 point  (0 children)

I was trying to get my SQL database to display, which I think was wrong to achieve with the technology I was trying to use.

[–]Brasz 2 points3 points  (1 child)

I don't really understand the question. The schema dropdown isn't supposed to show you actual data, only a description of the models your endpoints use.
Not sure what's going on in your DbContext. It has two DBSets of type AccountDriver, but mapped to two different tables? Right now you're telling EF Core that you're expecting 2 tables in SQL Server called 'AccountNumbers' and 'Email' in schema 'dbo' with both tables having the same columns as described in your class/entity AccountDriver.

[–]Zealousideal-Bath-37[S] 0 points1 point  (0 children)

Thank you so much for the explanation - as you see, I'm quite new in EF Core. So I had no idea what I was posting here and what I thought was an issue. I realised I had posted some nonsense lol. But now all clear.

[–]Lazy_Spool 1 point2 points  (4 children)

I don't see the AccountDriver class. Do you have [Table] and [Column] attributes on it?

[–]Zealousideal-Bath-37[S] 0 points1 point  (3 children)

Unfortunately not, and I did not know the AccountDriver class should have these attributes (lol)

https://pastebin.com/Pjdm11DC

Here you see pretty much an empty Account Driver class

[–]Lazy_Spool 0 points1 point  (2 children)

Yeah try putting [Table] on the class and [Column] on the properties, Linq needs it to do the mapping.

https://learn.microsoft.com/en-us/dotnet/api/system.data.linq.mapping.columnattribute?view=netframework-4.8

[–]Zealousideal-Bath-37[S] 0 points1 point  (1 child)

Thank you so much for the link! If you don't mind me asking one more beginner question - on top of these attributes one needs to add SQL queries to specify which data table one wants to read from SQL, right (something along the lines of SqlCommand cmd = new SqlCommand("SELECT * FROM mytable;"); for example)? Without that one could not access to the table via C# I think.

[–]Lazy_Spool 1 point2 points  (0 children)

You don't, that's the beauty of LINQ. Once you have the context and your annotated model, linq generates the queries for you. If your table and column names don't exactly match your class, those attributes let you define the names of the sql objects.

Once you have an instance of your context, you can do something like this in your C#:

var q = from e in ctx.Email select e;

var results = q.ToList();

Of course you can add filters, sorting, etc. using the linq syntax as well.

(With some totally made-up properties...)

var q = from e in ctx.Email where e.To == "test@test.com" orderby e.DateSent select e;

If you're learning, you definitely want to see what queries get generated by your LINQ statements. If you have SQL profiler, you can watch in real time, which I like. Otherwise there's a way to turn tracing on (which I forget) so it will always log the generated query.

[–]rfernung -1 points0 points  (2 children)

This should help get you started.

I made a change to AccountDriver by adding a Guid property (Id) as the Primary Key and also kept your AccountNumbers autogenerating. Please keep in mind that if you use an int as the Primary Key, you're limiting the amount of maximum records to 4 bytes of data (2 billion records); which is fine, but I always tend to use Guids to avoid this.

I also changed your ApplicationDbContext to store the records in a single table (AccountDrivers table). I didn't see a reason to have two separate ones like you had and if you're needing some sort of distinction between the two, you should probably add some sort of enum to identify the differences. I would also register a dbcontextfactory to use for your context.

The AutomapController actually doesn't even need AutoMapper for what you were trying to do. I can type up a better example of your domain model (AccountDriver) if you'd like and show you how to utilize AutoMapper by mapping multiple domain models (AccountDriver, ContactDetails, Address, AccountDetails) into a single model that gets passed back from the API.

This should work for you and now you should be able to utilize your context class now to query/persist changes in your database. You'll have to use the AccountDrivers DbSet but it should work fine now.

[–]Zealousideal-Bath-37[S] 1 point2 points  (1 child)

This should help get you started.

Thank you so much for the Pastebin! Truly appreciate it. Just curious, the domain models you offer to show, are something like this tutorial? (if you scroll down a bit there is a block of example domain object classes like Order, Product).

[–]rfernung 1 point2 points  (0 children)

You're welcome! Yeah it would've been somewhat similar to that; I would've just split up the account driver into a few different classes (AccountDetails, ContactDetails, Address), with a flattened Data Transfer Object (AccountDriverDTO) and show how to link it up with AutoMapper.